图的边数较少时,采用邻接矩阵存储图会浪费大量的空间。因此考虑把数组与链表结合在一次来存储,并提出了邻接表的概念。
关于无向图的邻接矩阵存储可参考我的上一篇博客。
邻接表的处理方式:
1.图中顶点用一个一维数组存储,当然,顶点也可用单链表存储,不过数组可以更加方便地读取顶点信息。
2.图中每个顶点Vi的所有邻接点构成一个线性表,由于邻接点的个数不确定,所以选择用单链表来存储。
无向图邻接表结构如下图所示:
code部分(无向图):
#include <stdio.h>
#include <stdlib.h>
//边数相对顶点较少的图采用邻接表的形式存储,这个邻接表的代码有问题
#define MAXVEX 100
typedef struct EdgeNode // 边表结点
{
int adjvex; // 邻接点域,存储该顶点对应的下标
int weight; // 用于存储权值,对于非网图可以不需要
struct EdgeNode *next; // 链域,指向下一个邻接点
} EdgeNode;
typedef struct VertexNode // 顶点表结点
{
char data; // 顶点域,存储顶点信息
EdgeNode *firstEdge; // 边表头指针
} VertexNode, AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numVertexes, numEdges; // 图中当前顶点数和边数
} GraphAdjList;
// 建立图的邻接表结构
void CreateALGraph(GraphAdjList *G)
{
int i, j, k, w;
EdgeNode *e;
printf("请输入顶点数和边数:\n");
scanf("%d %d", &G->numVertexes, &G->numEdges);
// 读取顶点信息,建立顶点表
for( i=0; i < G->numVertexes; i++ )
{
//scanf("%c", &G->adjList[i].data);
G->adjList[i].data = 'a'+i;
G->adjList[i].firstEdge = NULL; // 初始化置为空表
}
for( k=0; k < G->numEdges; k++ )
{
printf("请输入边(Vi,Vj)上的顶点序号和边的权值,用空格隔开:\n");
scanf("%d %d %d", &i, &j, &w);
e = (EdgeNode *)malloc(sizeof(EdgeNode));
e->adjvex = j; // 邻接序号为j
e->weight = w;
e->next = G->adjList[i].firstEdge;
G->adjList[i].firstEdge = e;
//因为是无向图,彼此相对称
e = (EdgeNode *)malloc(sizeof(EdgeNode));
e->adjvex = i; // 邻接序号为i
e->weight = w;
e->next = G->adjList[j].firstEdge;
G->adjList[j].firstEdge = e;
}
}
//打印邻接表
void PrintfGraphA(GraphAdjList G)
{
for(int i = 0; i < G.numVertexes; i++)
{
printf("%d %c\t", i,G.adjList[i].data);
EdgeNode *p = G.adjList[i].firstEdge;
while(p)
{
printf("%d %d\t", p->adjvex,p->weight);
p = p->next;
}
printf("\n");
}
}
int main()
{
GraphAdjList G;
CreateALGraph(&G);
PrintfGraphA(G);
return 0;
}
结果: