数据结构基础 图的存储结构

173 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

邻接矩阵
直接用一个二维数组存储

采用程序化的步骤:

  1. 建立包含全部顶点但没有边的图
  2. 逐条插入边, 从而建立一个图
#include <iostream>
#include <algorithm>
#include <climits>
#include <cstdlib>
#include <cstring>
using namespace std;
const int MaxV = 100;

/*图结点的定义*/
typedef struct GNode{
	int Nv;	//顶点数
	int Ne;	//边数
	int F[MaxV][MaxV];	//邻接矩阵
	char Data[MaxV];	//顶点数据, 若顶点无数据, data[]可以不出现
} * MGraph;

/*边的定义*/
typedef struct ENode{
	int v1, v2; //有向边<v1, v2>
	int Weight;	//边权重
} * Edge;

MGraph CreateGraph(int Nv)
{	/*初始化一个有Nv个顶点但没有边的图*/
	MGraph G = (MGraph)malloc(sizeof(GNode));
	//MGraph G = new GNode{0};
	G->Nv = Nv; G->Ne = 0;
	for (int i = 0; i < Nv; i++)
		for (int j = 0; j < Nv; j++)
			G->F[i][j] = INT_MAX;
	return G;
}
void InsertEdge(MGraph G, Edge E)
{	/*插入边<v1, v2>*/
	G->F[E->v1][E->v2] = E->Weight;
	//G->F[E->v2][E->v2] = E->Weight;	//如果是有向图, 还要插入边<v2, v1>
}
MGraph BuildGraph()
{	/*建立一个完整的图*/
	MGraph G;
	Edge E = (Edge)malloc(sizeof(ENode));
	//Edge E = new ENode;
	int Nv;
	cin >> Nv;
	G = CreateGraph(Nv);	//初始化一个图
	cin >> G->Ne;	//指针有地址存储图后, 可直接对图进行访问
	for (int i = 0; i < G->Ne; i++)
	{
		cin >> E->v1 >> E->v2 >> E->Weight;
		InsertEdge(G, E);
	}
	free(E);
	//delete E;
	// for (int i = 0; i < G->Nv; i++)	//如果顶点有数据, 读入数据
	// 	cin >> G->Data[i];			//下标是顶点的数字编号, char型是名称显示
	return G;
}

int main()
{
	//cout << "输入顶点数和边数, 然后输入边<v1, v2>, Weight" << endl;
	MGraph G = BuildGraph();
	for (int i = 0; i < G->Nv; i++)	//输出邻接矩阵
	{
		for (int j = 0; j < G->Nv; j++)
			cout << G->F[i][j] << " ";
		cout << endl;
	}
	free(G);
	//delete G;
	system("pause");
	return 0;
}

示例图:
image.png

输入

5 8
0 2 6
0 3 3
1 0 9
1 2 4
2 4 7
3 1 5
3 4 8
4 3 6

运行结果
那很大的数表示无穷大

邻接表

image.png

#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int MaxV = 100;

/*边的定义*/
typedef struct ENode{
	int v1, v2;	//有向边<v1, v2>
	int Weight;	//边权重
} * Edge;
/*邻接点的定义*/
struct AdjVNode{
	int AdjV;		//邻接点下标v
	int Weight;		//边权重, 顶点表头结点u, 则边<u, v>
	AdjVNode *Next;	//指向下一邻接点的指针
};
/*顶点表头结点的定义*/
typedef struct VNode{
	AdjVNode *FirstEdge;	//边表头指针
	int Data;	//存顶点数据, 多数情况顶点无数据, 此时Data可以不用出现
} AdjList[MaxV];
/*图结点的定义*/
typedef struct GNode{
	int Nv, Ne;	//顶点和边数
	AdjList L;
} * LGraph;

LGraph CreateGraph(int Nv)
{	/*初始化一个有Nv个顶点但没有边的图*/
	LGraph G = (LGraph)calloc(1, sizeof(GNode));	//申请存储空间并初始化
	//LGraph G = new GNode{0};
	G->Nv = Nv;
	return G;
}
void InsertEdge(LGraph G, Edge E)
{	/*边的插入, 每次的插在邻接顶点表头*/
	AdjVNode *newVNode;
	/*插入边<v1, v2>*/
	newVNode = (AdjVNode *)malloc(sizeof(AdjVNode));
	newVNode->AdjV = E->v2; newVNode->Weight = E->Weight;	//将边E的数据赋给newVNode
	newVNode->Next = G->L[E->v1].FirstEdge;		//两部操作把v2插入v1表头, 构成有向边<v1, v2>
	G->L[E->v1].FirstEdge = newVNode;
	/*若是无向图, 再插入边<v2, v1>*/
	// newVNode = (AdjVNode *)malloc(sizeof(AdjVNode));
	// newVNode->AdjV = E->v1; newVNode->Weight = E->Weight;	//将边E的数据赋给newVNode
	// newVNode->Next = G->L[E->v2].FirstEdge; 	//两部操作把v2插入v1表头, 构成有向边<v1, v2>
	// G->L[E->v2].FirstEdge = newVNode;
}
LGraph BuildGraph()
{
	int Nv;
	LGraph G;
	Edge E = (Edge)malloc(sizeof(ENode));
	//Edge E = new ENode;
	cin >> Nv; G = CreateGraph(Nv);	//初始化
	cin >> G->Ne;
	for (int i = 0; i < G->Ne; i++)
	{
		cin >> E->v1 >> E->v2 >> E->Weight;
		InsertEdge(G, E);
	}
	free(E);	//不用了, 记得free
	//delete E;
	/*如果需要Data*/
	// for (int i = 0; i < G->Nv; i++)
	// 	cin >> G->L[i].Data;
	return G;
}

int main()
{
	LGraph G = BuildGraph();
	AdjVNode *V;
	for (int i = 0; i < G->Nv; i++)
	{
		cout << i << "->";
		while (G->L[i].FirstEdge)
		{
			AdjVNode *V = G->L[i].FirstEdge;
			cout << "(" << V->AdjV << " W:" << V->Weight << ")->";
			G->L[i].FirstEdge = V->Next;
			free(V);	//每次访问完后删除
		}
		cout << "NULL" << endl;
	}
	free(G);
	//delete G;
	system("pause");
	return 0;
}

运行结果

在这里插入图片描述