建立图-邻接表
邻接表是图的一种顺序存储和链式存储相结合的存储方法,对于邻接矩阵存储方法中,边数相对顶点较少的图造成的空间浪费,在邻接表中很好的避免了这个问题。
对于图中每个顶点Vi,将邻接于Vi的所有顶点Vj链成一个单链表,单链表中的节点称为表节点,这个单链表就称为顶点Vi的邻接表,对每个顶点的邻接表建立一个头节点,这些头节点通常以顺序结构存储,即为了便于随机访问任意顶点的邻接表,可以将所有点的邻接表的头节点放到一个数组里,这个头节点数组称为顶点表,因此,在图的邻接表表示中有两种节点结构。
关于邻接表的几点说明:
1:一个图的邻接矩阵的表示是唯一的,但其邻接表不唯一
2:为了便于确定有向图顶点的入度,可以为有向图建立逆邻接表,而i号单链表中的节点个数只是顶点Vi的出度
图的邻接表存储如下:
1 //建立无向图邻接表 2 #include<stdio.h> 3 #include<malloc.h> 4 #define MAX_VEX 100 //最大顶点数为100 5 6 typedef struct node{ //定义表节点 7 int adjvex; //邻接顶点域 8 struct node *next; //指向下一个邻接顶点的指针域 9 //char info; //若为带权无向图,表示权值,加上数据域info 10 }Arcnode; 11 typedef struct vexnode{ //定义头节点 12 int vertex; //顶点域 13 Arcnode *firstacr; //边表头指针 14 }Vexnode; //vexnode事以邻接表方式存储的图类型 15 16 Vexnode adjlist[MAX_VEX]; //定义头节点数组 17 18 int creatadjlist() //建立邻接表 19 { 20 Arcnode *ptr; 21 int arcnum,vexnum,k,v1,v2; 22 printf("请输入顶点数和边数:\n"); 23 scanf("%d %d",&vexnum,&arcnum); 24 for(k = 1;k <= vexnum;k++) 25 adjlist[k].firstacr = 0; //为邻接链表数组的元素链域赋初值 26 for(k = 0;k < arcnum;k++) //为adjlist数组的个元素分别建立各自的链表 27 { 28 printf("v1,v2="); 29 scanf("%d %d",&v1,&v2); 30 ptr = (Arcnode *)malloc(sizeof(Arcnode)); 31 ptr->adjvex = v2; //将顶点v2插入到链表中,使得节点插入后单链表仍然有序,链表采用头插法 32 ptr->next = adjlist[v1].firstacr; 33 adjlist[v1].firstacr = ptr; //将邻接点v2插入表头节点v1之后 34 //以下四行代码只对无向图起作用 35 ptr = (Arcnode *)malloc(sizeof (Arcnode)); 36 ptr->adjvex = v1; 37 ptr->next = adjlist[v2].firstacr; 38 adjlist[v2].firstacr = ptr; 39 } 40 41 return vexnum; 42 } 43 44 int main() 45 { 46 int i, n; 47 Arcnode *p; 48 n = creatadjlist(); 49 printf("所建图的邻接表为:\n"); 50 for(i = 1;i <= n;i++) 51 { 52 printf("%d==>",i); 53 p = adjlist[i].firstacr; 54 while(p != NULL) 55 { 56 printf("-- -->%d",p->adjvex); 57 p = p->next; 58 } 59 printf("\n\n"); 60 } 61 62 return 0; 63 }