邻接表 与 邻接矩阵

邻接表 —— 稀疏图使用的图的储存结构

邻接矩阵 —— 稠密图使用的图的储存结构

数据结构课代码实现 之 邻接表 与 邻接矩阵

简要理解

邻接表 —— 链式储存结构 对图中每个顶点建立一个单链表来表示依附于该节点的边

邻接矩阵 —— 使用两个数组分别储存数据元素 (顶点) 的信息 和 数据元素之间的关系 (边或弧) 的信息

邻接表

结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
typedef struct ArcNode
{
int adjvex; // 该弧指向的顶点的位置
struct ArcNode *nextarc; // 指向下一条弧的指针
//InfoType *info; 该弧相关信息的指针
}ArcNode;

typedef struct VNode
{
int data; // 顶点信息
ArcNode *firstarc; // 指向第一条依附该顶点的弧的指针
}VNode, AdjList[MAX_VERTEX_NUM];


typedef struct
{
AdjList vertices;
int vexnum, arcnum; // 图的当前 顶点数 和 弧数
int kind; // 图的种类标志
}ALGraph;

创建邻接表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void CreateGraph(ALGraph &G)
{
cout << "输入图的点数 与 弧数:" << endl;
cin >> G.vexnum >> G.arcnum;
for(int i = 0;i < G.vexnum;i++)
{
cout << "输入第 " << i << " 号节点的data" << endl;
cin >> G.vertices[i].data;
G.vertices[i].firstarc = (ArcNode *)malloc(sizeof(ArcNode));
ArcNode* temp = G.vertices[i].firstarc;
char x;
cout << "输入第 " << i << " 号节点的邻接点,空格分开,#结束" << endl;
cin >> x;
if(x != '#')
temp->adjvex = x - 48;
while(x != '#')
{
temp->nextarc = (ArcNode *)malloc(sizeof(ArcNode));
temp = temp->nextarc;
cin >> x;
if(x != '#')
temp->adjvex = x - 48;
}
temp->nextarc = NULL;
}
}

邻接矩阵

结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef enum{DG, DN, UDG, UDN} GraphKind;          // {有向图,有向网,无向图,无向网}

typedef struct ArcCell
{
int adj; // 有权图 表顶点之间的权值
// 无权图用 0 或 1 表是否相邻

// 可储存一些与弧相关的信息
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct
{
int vexs[MAX_VERTEX_NUM]; // 顶点向量
AdjMatrix arcs; // 邻接矩阵
int vexnum, arcnum; // 图的 顶点数 和 弧数
GraphKind kind; // 图的种类
}MGraph;

LocateVex操作

1
2
3
4
5
6
7
8
int LocateVex(MGraph g, int x)
{
for(int i = 0;i < g.vexnum;i++)
{
if(g.vexs[i] == x) // 输入顶点向量值 求 顶点坐标
return i;
}
}

创建矩阵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
int CreateUDN(MGraph &G)
{
cout << "输入图的点数 与 弧数:" << endl;
cin >> G.vexnum >> G.arcnum;
for(int i = 0; i < G.vexnum; i++)
{
cout << "依次输入图的各点的 值:" << endl;
cin >> G.vexs[i];
}
for(int i = 0; i < G.vexnum; i++)
for(int j = 0; j < G.vexnum; j++)
G.arcs[i][j].adj = INFINITY;
for(int k = 0; k < G.arcnum; k++)
{
int v1, v2, w;
int i, j;
cout << "依次输入每条弧的 起点 与 终点(输入点的值 不是坐标) 与 权值:" << endl;
cin >> v1 >> v2 >> w;
i = LocateVex(G, v1);
j = LocateVex(G, v2);
G.arcs[i][j].adj = w;
G.arcs[j][i] = G.arcs[i][j];
}
return OK;
}

int CreateGraph(MGraph &G)
{
string a;
cout << "输入图的类型:" << endl;
cin >> a;
if(a == "DG") G.kind = DG;
if(a == "DN") G.kind = DN;
if(a == "UDG") G.kind = UDG;
if(a == "UDN") G.kind = UDN;
switch(G.kind)
{
case DG: return CreateDG(G);
case DN: return CreateDN(G);
case UDN: return CreateUDN(G);
case UDG: return CreateUDG(G);
default : return ERROR;
}
return OK;
}

无向图的 弧 相当于是有向图 给相应起点与终点间 建立两个方向的 弧

有向图 有向网 无向图就不写了,图的种类 决定了 创图时是否正反建边 或者 是否存在权值