之前我们介绍过图的邻接矩阵存储法,它的空间和时间复杂度都是N2,现在我来介绍另外一种存储图的方法:邻接表,这样空间和时间复杂度就都是M。对于稀疏图来说,M要远远小于N2。先上数据,如下。
1
2
3
4
5
6
|
4 5
1 4 9
4 3 8
1 2 5
2 4 6
1 3 7
|
第一行两个整数n m。n表示顶点个数(顶点编号为1~n),m表示边的条数。接下来m行表示,每行有3个数x y z,表示顶点x到顶点y的边的权值为z。下图就是一种使用链表来实现邻接表的方法。
上面这种实现方法为图中的每一个顶点(左边部分)都建立了一个单链表(右边部分)。这样我们就可以通过遍历每个顶点的链表,从而得到该顶点所有的边了。
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 50
struct node//边表结点
{
int adjvex;//邻接点域
node *next;//链域
};
struct vnode//顶点表结点
{
int vertex;//顶点域
node * firstedge;//边表头指针
};
struct graph
{
vnode* adjlist;
int n;
int e;
};
void CreateGraph(graph *G)
{
int v,e;
printf("请输入顶点数和边数:");
scanf("%d%d",&v,&e);
G->n=v;
G->e=e;
printf("请输入顶点编号:");
for(int i=0;i<G->n;i++)
{
scanf("%d",&(G->adjlist[i].vertex));
G->adjlist[i].firstedge=NULL;
}
printf("请输入两个顶点组成的边,示例:0 1\n");
int v1,v2;
for(int j=0;j<G->e;j++)
{
node *s=(node*)malloc(sizeof(node));
scanf("%d%d",&v1,&v2);
s->adjvex=v2;
s->next=G->adjlist[v1].firstedge;
G->adjlist[v1].firstedge=s;
}
}
void main()
{
int i,j;
graph *G=(graph*)malloc(sizeof(graph));
G->adjlist=(vnode*)malloc(sizeof(vnode)*MAXSIZE);
CreateGraph(G);
for (i = 0; i < G->n; i++)
{
while (G->adjlist[i].firstedge)
{
printf("%d -> ", G->adjlist[i].vertex);
printf("%d\n", G->adjlist[i].firstedge->adjvex);
G->adjlist[i].firstedge = G->adjlist[i].firstedge->next;
}
}
}