邻接表是图结构中的一种存储结构,适用于存储无向图和有向图。
邻接表存储图的实现方式是,给图中的各个顶点独自建立一个链表,用节点存储该顶点,用链表中其他节点存储各自的临界点。
与此同时,为了便于管理这些链表,通常会将所有链表的头节点存储到数组中(也可以用链表存储)。也正因为各个链表的头节点存储的是各个顶点,因此各链表在存储临界点数据时,仅需存储该邻接顶点位于数组中的位置下标即可。
将图画出来,在编写代码思路会比较清晰
从图中我们知道,顶点表的各个结点由data和firstedge两个域表示,data是数据域,存储顶点的信息。
firstedge是指针域,指向边表的第一个结点,即此顶点的第一个邻接点。
边表结点由adjvex和next两个域组成。adjvex是邻接点域,存储某顶点的邻接点在顶点表中的下标,next则存储指
向边表中下一个结点的指针,比如v1顶点与v0、v2互为邻接点,则在v1的边表中,adjvex分别为v0的0和v2的2.
如果想知道某个顶点的度,就去查找这个顶点的边表中结点的个数。
若要判断顶点vi和vj是否存在边,只需要测试顶点vi的边表adjvex中是否存在结点vj的下标就行了。
若求顶点的所有邻接点,其实就是对此顶点的边表进行遍历,得到的adjvex域对应的顶点就是邻接点。
代码如下:
#include "stdio.h"
#include "stdlib.h"
#define Maxvew 100 //顶点数量最大值
typedef struct Edgenode //邻接结点
{
int adjvex; //邻接结点存储的数组下标
int weight; //用于存储权值,对于非网图可以不需要
struct Edgenode *next; //链域,指向下一个邻接点
}Edgenode;
typedef struct Vertexnode //顶点 表节点
{
char data; //顶点域,存储顶点信息
Edgenode *firstedge; //边表头指针
}Vertexnode,AdjList[Maxvew];
typedef struct // 数组、顶点、边 结构体
{
AdjList adjList; //顶点数组
int numVertexes,numEdges;//图中当前顶点数和边数
}GrapAdList;
void CreateALGraph(GrapAdList *G) //创建邻接图表
{
int i,j,k;
Edgenode *e; //创建邻接结点
printf("输入顶点数和边数:\n");
scanf("%d,%d",&G->numVertexes,&G->numEdges);//输入顶点数和边的数量
for(i=0;i<G->numVertexes;i++) //for循环 顶点的数量
{
scanf(&G->adjList[i].data); //输入顶点存储的数据data
G->adjList[i].firstedge = NULL; //设置顶点的邻接结点先为空
}
for(k=0;k<G->numEdges;k++) //for循环 边的数量
{
printf("输入边(vi,vj)上的顶点序号:\n");
scanf("%d,%d",&i,&j); //输入边的弧头和弧尾
e = (Edgenode *)malloc(sizeof(Edgenode)); //给邻接结点分配内存
e->adjvex=j; //将数字j 代入邻接点的数据域里
e->next=G->adjList[i].firstedge; //邻接点的next 指向NULL (链表操作)
G->adjList[i].firstedge=e; //顶点的firstedge[i]指针指向该邻接结点
e=(Edgenode *)malloc(sizeof(Edgenode)); //再次分配出个邻接结点
e->adjvex=i; //将i的值代入邻接结点的数据域
e->next=G->adjList[j].firstedge; //邻接点的next 指向NULL (链表操作)
G->adjList[j].firstedge=e; //邻接点接在顶点结点adjList[j]后
}
}
void digui(Edgenode *k) //使用递归 打印邻接表的后续数据
{
if(k==NULL) //如果邻接表的第二链为空 则输出换行 停止递归
{
printf("\n");
}
else //否则
{
printf("%d->\t",k->adjvex); //打印出后续数据
k=k->next; //递归操作 替换参数 循环递归
return digui(k);
}
}
void printfGraph(GrapAdList *G)
{
int i;
for(i=0;i<G->numVertexes;i++) //for循环顶点的个数
{
printf("%d\t",i); //打印出顶点数组下标
if(G->adjList[i].firstedge==NULL) //如果邻接点为空 则换行
{
printf("\n");
}
else{
printf("%d->\t",G->adjList[i].firstedge->adjvex); //否则输出后续邻接结点 数据
Edgenode *k=G->adjList[i].firstedge->next; //递归操作 创建邻接结点k指针指向目前递归到的指针节点的next
digui(k); //递归
}
}
}
int main()
{
GrapAdList G; //数据 结构体
CreateALGraph(&G); //创建邻接表
printfGraph(&G); //输出邻接表
return 0;
}
编译结果:
代码有些许漏洞,待后续改进。。。