图的存储结构——邻接表法
一、邻接表
由顶点表和边表构成,顶点表由顶点域(data)和指向第一条邻接边的指针(firstarc)构成,边表(邻接表)结点由邻接点域(adjvex)和指向下一条邻接边的指针域(next)构成。
二、代码实现
(1)图的邻接表存储结构定义
#define MaxVertexNum 30
typedef char VertexType;
typedef int ArcValue;
// 边表 结点
typedef struct ArcNode {
int adjvex; //邻接结点,该顶点对应的下标
ArcValue value; //权值
struct ArcNode* next; //链域指向下一个结点
}ArcNode;
//顶点表结点
typedef struct VertexNode {
VertexType data; //存储 顶点的数据
ArcNode* firstarc; //边表头指针
}VertexNode,AdjList[MaxVertexNum];
//邻接表
typedef struct graph {
AdjList adjList; //邻接表 数组
int verNum, arcNum; //当前定点数、边数
}GraphAdjList;
(2)创建邻接表
创建顶点表及边表,如若为有向图,结点只插入一次。无向图则插入两次,顶点为双向关联。
void CreateAdjListGraph(GraphAdjList* G) {
printf("有向图 1,无向图0:");
int flag = 0;
scanf("%d", &flag);
//初始化邻接表
for (int i = 0; i < MaxVertexNum; i++) {
G->adjList[i].firstarc = NULL;
}
printf("输入顶点、边个数(空格间隔):");
scanf("%d%d", &G->verNum, &G->arcNum);
/*建立顶点表*/
for (int i = 0; i < G->verNum; i++) {
printf("请输入第%d个顶点的元素:", i + 1);
fflush(stdin);
scanf(" %c", &G->adjList[i].data);
G->adjList[i].firstarc = NULL;
}
/*建立边表*/
int vi, vj;
ArcValue value;
for (int i = 0; i < G->arcNum; i++) {
printf("请输入vi vj w(空格间隔):");
scanf("%d%d%d", &vi, &vj, &value);
ArcNode* newNode;
newNode = (ArcNode*)malloc(sizeof(ArcNode));
newNode->next = G->adjList[vi - 1].firstarc;
newNode->adjvex = vj;
newNode->value = value;
G->adjList[vi - 1].firstarc = newNode;
if (flag==0) {//判断是否为有向图
ArcNode* newNode2;
newNode2 = (ArcNode*)malloc(sizeof(ArcNode));
newNode2->next = G->adjList[vj - 1].firstarc;
newNode2->adjvex = vi;
newNode2->value = value;
G->adjList[vj - 1].firstarc = newNode2;
}
}
}
(3)打印输出邻接表
void PrintGraphVertex(GraphAdjList* G) {
printf("结点:\n");
for (int i = 0; i < G->verNum; i++) {
printf("%d\t%c\t", i+1, G->adjList[i].data);
ArcNode* p = G->adjList[i].firstarc;
while (p!=NULL) {
printf("(%d,%d)\t", p->adjvex,p->value);
p = p->next;
}
if (p==NULL) {
printf("^");
}
printf("\n\n");
}
}
三、完整代码
#include<stdio.h>
#include<stdlib.h>
#define MaxVertexNum 30
typedef char VertexType;
typedef int ArcValue;
// 边表 结点
typedef struct ArcNode {
int adjvex; //邻接结点,该顶点对应的下标
ArcValue value; //权值
struct ArcNode* next; //链域指向下一个结点
}ArcNode;
//顶点表结点
typedef struct VertexNode {
VertexType data; //存储 顶点的数据
ArcNode* firstarc; //边表头指针
}VertexNode,AdjList[MaxVertexNum];
//邻接表
typedef struct graph {
AdjList adjList; //邻接表 数组
int verNum, arcNum; //当前定点数、边数
}GraphAdjList;
void CreateAdjListGraph(GraphAdjList* G) {
printf("有向图 1,无向图0:");
int flag = 0;
scanf("%d", &flag);
for (int i = 0; i < MaxVertexNum; i++) {
G->adjList[i].firstarc = NULL;
}
printf("输入顶点、边个数(空格间隔):");
scanf("%d%d", &G->verNum, &G->arcNum);
/*建立顶点表*/
for (int i = 0; i < G->verNum; i++) {
printf("请输入第%d个顶点的元素:", i + 1);
fflush(stdin);
scanf(" %c", &G->adjList[i].data);
G->adjList[i].firstarc = NULL;
}
/*建立边表*/
int vi, vj;
ArcValue value;
for (int i = 0; i < G->arcNum; i++) {
printf("请输入vi vj w(空格间隔):");
scanf("%d%d%d", &vi, &vj, &value);
ArcNode* newNode;
newNode = (ArcNode*)malloc(sizeof(ArcNode));
newNode->next = G->adjList[vi - 1].firstarc;
newNode->adjvex = vj;
newNode->value = value;
G->adjList[vi - 1].firstarc = newNode;
if (flag==0) {
ArcNode* newNode2;
newNode2 = (ArcNode*)malloc(sizeof(ArcNode));
newNode2->next = G->adjList[vj - 1].firstarc;
newNode2->adjvex = vi;
newNode2->value = value;
G->adjList[vj - 1].firstarc = newNode2;
}
}
}
void PrintGraphVertex(GraphAdjList* G) {
printf("结点:\n");
for (int i = 0; i < G->verNum; i++) {
printf("%d\t%c\t", i+1, G->adjList[i].data);
ArcNode* p = G->adjList[i].firstarc;
while (p!=NULL) {
printf("(%d,%d)\t", p->adjvex,p->value);
p = p->next;
}
if (p==NULL) {
printf("^");
}
printf("\n\n");
}
}
int main() {
GraphAdjList* G;
G = (GraphAdjList*)malloc(sizeof(GraphAdjList));
CreateAdjListGraph(G);
PrintGraphVertex(G);
}