一、邻接表示意图
邻接表相比于邻接矩阵来说,大大减少了存储空间的浪费情况。如图1-1为邻接表示意图,其中V0~V3表示的是图的顶点(vertex),后面跟随的则是邻接节点。邻接节点的数字表示顶点下一个连接的顶点的索引,如V1邻接节点的数字为2和0,则表示V1节点连接了V2和V0节点,如图1-2.
图1-1
图1-2
二、代码实现
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define MAX_VERTEX_NUM 10
char name[5] = {'a', 'b', 'c', 'd', 'e'};
typedef struct adjNode
{
int index;
struct adjNode *next;
} adjNode, *padjNode;
typedef struct verNode
{
char verName;
adjNode *first;
} verNode, verMat[MAX_VERTEX_NUM];
typedef struct graph
{
int verNum, adjNum;
verMat vm;
} graph, *pgraph;
void initGraph(pgraph *g)
{
(*g) = (pgraph)malloc(sizeof(graph));
(*g)->verNum = (*g)->adjNum = 0;
for (int i = 0; i < MAX_VERTEX_NUM; i++)
{
(*g)->vm[i].verName = '#';
}
}
void insertVertex(pgraph *g, char name)
{
for (int i = 0; (*g)->verNum != MAX_VERTEX_NUM; i++)
{
if ((*g)->vm[i].verName == '#')
{
(*g)->vm[i].verName = name;
(*g)->vm[i].first = NULL;
break;
}
}
(*g)->verNum++;
}
void showAllVerName(pgraph *g)
{
int index = 0;
printf("图的顶点信息:");
while (index != (*g)->verNum)
{
printf("%c ", (*g)->vm[index].verName);
index++;
}
}
/*
构建图:
a → b
↓ ↗ ↓
c ← d ← e
source,direction∈(1~MAX_VERTEX_NUM)
*/
void pointTo(pgraph *g, int source, int direction)
{
padjNode node = (padjNode)malloc(sizeof(adjNode));
node->index = direction;
node->next = NULL;
// 当顶点无任何边
if ((*g)->vm[source - 1].first == NULL)
{
(*g)->vm[source - 1].first = node;
printf("%c->%c成功!\n", (*g)->vm[source - 1].verName, (*g)->vm[direction - 1].verName);
(*g)->adjNum++;
return;
}
// 当顶点有一条或一条以上的边
else
{
padjNode q = (*g)->vm[source - 1].first;
// 当顶点链接的第一条边对应的顶点已存在
if (q->index == direction)
{
printf("已存在%c->%c的边\n", (*g)->vm[source - 1].verName, (*g)->vm[direction - 1].verName);
return;
}
// 移动到最后一条边
while (q->next != NULL)
{
q = q->next;
// 当顶点链接的边对应的顶点已存在
if (q->index == direction)
{
printf("已存在%c->%c的边\n", (*g)->vm[source - 1].verName, (*g)->vm[direction - 1].verName);
return;
}
}
// 在最后插入邻接节点
q->next = node;
printf("%c->%c成功!\n", (*g)->vm[source - 1].verName, (*g)->vm[direction - 1].verName);
(*g)->adjNum++;
return;
}
}
void showAllAdjnodeOfNode(pgraph *g)
{
padjNode q;
for (int i = 0; i < (*g)->verNum; i++)
{
printf("%c", (*g)->vm[i].verName);
q = (*g)->vm[i].first;
for (int j = 0; q != NULL; j++)
{
printf("->%c",(*g)->vm[q->index-1].verName);
q = q->next;
}
printf("\n");
}
}
int main(int argc, char const *argv[])
{
pgraph g;
initGraph(&g);
for (int i = 0; i < 5; i++)
{
insertVertex(&g, name[i]);
}
pointTo(&g, 1, 2);
pointTo(&g, 1, 3);
pointTo(&g, 2, 4);
pointTo(&g, 4, 3);
pointTo(&g, 3, 2);
pointTo(&g, 5, 4);
showAllAdjnodeOfNode(&g);
showAllVerName(&g);
return 0;
}