6.4.2 邻接表(稀疏图)
采用邻接表表示法创建无向图
//算法6.2 采用邻接表表示法创建无向图
#include <stdio.h>
#include <stdlib.h>
#define MVNum 100
typedef int OtherInfo; //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef struct ArcNode
{
int adjvex;
struct ArcNode* nextarc;
OtherInfo info;
}ArcNode; //边结点
typedef struct VNode
{
VerTexType data;
ArcNode* firstarc;
}VNode,AdjList[MVNum]; //表头结点
typedef struct
{
AdjList vertices; //存储所有顶点
int vexnum; //顶点总数
int arcnum; //总边数
}ALGraph; //图的信息
void CreateUDG(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph &G);
int main()
{
ALGraph G = { {'\0',NULL}, 0,0};
CreateUDG(G);
printALGraph(G);
return 0;
}
void CreateUDG(ALGraph& G)
{
int i = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
int j = 0;
ArcNode *p1 = NULL;
ArcNode *p2 = NULL;
printf("请输入无向图的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入无向图的总边数:");
scanf_s(" %d", &G.arcnum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.vertices[i].data));
G.vertices[i].firstarc = NULL; //初始化
}
for (k = 0; k < G.arcnum; k++)
{
printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (ArcNode*)malloc(sizeof(ArcNode));
p1->adjvex = j;
p1->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = p1; //将新结点*p1插入顶点Vi的边表头部
p2 = (ArcNode*)malloc(sizeof(ArcNode));
p2->adjvex = i;
p2->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = p2; //将与*p1对称的新的边结点*p2插入顶点Vj的边表头部
}
}
//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
int i = 0;
for (i = 0; i < G.vexnum && (G.vertices[i].data != v); ++i)
{
;
}
return i;
}
//打印邻接表
void printALGraph(ALGraph& G)
{
int i = 0;
ArcNode* pMove = NULL;
for (i = 0; i < G.vexnum; i++)
{
printf("\n第%d个顶点为:%c", i + 1, G.vertices[i].data);
pMove = G.vertices[i].firstarc;
if (pMove)
{
printf("\n与第%d个顶点相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
while (pMove)
{
printf("%d ", pMove->adjvex);
pMove = pMove->nextarc;
}
}
else
{
printf("\n没有与第%d个顶点相邻接的顶点。", i + 1);
}
}
}
一个图的邻接矩阵表示是唯一的,但其邻接表表示不唯一。
不改变图中每个顶点的命名方式,也不改变图的边(每条边的起终点),
仅改变边的输入次序时,图的邻接表中每个顶点后面边表中的结点排序方式会发生变化。
因为图中的顶点没变,边也没变,每个顶点及其边表中的内容不会发生变化。
采用邻接表表示法创建有向图
//采用邻接表表示法创建有向图
#include <stdio.h>
#include <stdlib.h>
#define MVNum 100
typedef int OtherInfo; //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef struct ArcNode
{
int adjvex;
struct ArcNode* nextarc;
OtherInfo info;
}ArcNode; //边结点
typedef struct VNode
{
VerTexType data;
ArcNode* firstarc;
}VNode, AdjList[MVNum]; //表头结点
typedef struct
{
AdjList vertices; //存储所有顶点
int vexnum; //顶点总数
int arcnum; //总边数
}ALGraph; //图的信息
void CreateDG(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);
int main()
{
ALGraph G = { {'\0',NULL}, 0,0 };
CreateDG(G);
printALGraph(G);
return 0;
}
//采用邻接表表示法创建有向图
void CreateDG(ALGraph& G)
{
int i = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
int j = 0;
ArcNode* p1 = NULL;
ArcNode* p2 = NULL;
printf("请输入有向图的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入有向图的总边数:");
scanf_s(" %d", &G.arcnum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.vertices[i].data));
G.vertices[i].firstarc = NULL; //初始化
}
for (k = 0; k < G.arcnum; k++)
{
printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (ArcNode*)malloc(sizeof(ArcNode));
p1->adjvex = j;
p1->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = p1; //将新结点*p1插入顶点Vi的边表头部
}
}
//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
int i = 0;
for (i = 0; i < G.vexnum && (G.vertices[i].data != v); ++i)
{
;
}
return i;
}
//打印邻接表
void printALGraph(ALGraph& G)
{
int i = 0;
ArcNode* pMove = NULL;
for (i = 0; i < G.vexnum; i++)
{
printf("\n第%d个顶点为:%c", i + 1, G.vertices[i].data);
pMove = G.vertices[i].firstarc;
if (pMove)
{
printf("\n将第%d个顶点作为出度,与其相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
while (pMove)
{
printf("%d ", pMove->adjvex);
pMove = pMove->nextarc;
}
}
else
{
printf("\n将第%d个顶点作为出度,没有与其相邻接的顶点。", i + 1);
}
}
}
创建有向图的逆邻接表
//创建有向图的逆邻接表
#include <stdio.h>
#include <stdlib.h>
#define MVNum 100
typedef int OtherInfo; //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef struct ArcNode
{
int adjvex;
struct ArcNode* nextarc;
OtherInfo info;
}ArcNode; //边结点
typedef struct VNode
{
VerTexType data;
ArcNode* firstarc;
}VNode, AdjList[MVNum]; //表头结点
typedef struct
{
AdjList vertices; //存储所有顶点
int vexnum; //顶点总数
int arcnum; //总边数
}ALGraph; //图的信息
void CreateDG(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);
int main()
{
ALGraph G = { {'\0',NULL}, 0,0 };
CreateDG(G);
printALGraph(G);
return 0;
}
//创建有向图的逆邻接表
void CreateDG(ALGraph& G)
{
int i = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
int j = 0;
ArcNode* p1 = NULL;
ArcNode* p2 = NULL;
printf("请输入有向图的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入有向图的总边数:");
scanf_s(" %d", &G.arcnum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.vertices[i].data));
G.vertices[i].firstarc = NULL; //初始化
}
for (k = 0; k < G.arcnum; k++)
{
printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (ArcNode*)malloc(sizeof(ArcNode));
p1->adjvex = i;
p1->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = p1; //将新结点*p1插入顶点Vj的边表头部
}
}
//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
int i = 0;
for (i = 0; i < G.vexnum && (G.vertices[i].data != v); ++i)
{
;
}
return i;
}
//打印逆邻接表
void printALGraph(ALGraph& G)
{
int i = 0;
ArcNode* pMove = NULL;
for (i = 0; i < G.vexnum; i++)
{
printf("\n第%d个顶点为:%c", i + 1, G.vertices[i].data);
pMove = G.vertices[i].firstarc;
if (pMove)
{
printf("\n将第%d个顶点作为入度,与其相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
while (pMove)
{
printf("%d ", pMove->adjvex);
pMove = pMove->nextarc;
}
}
else
{
printf("\n将第%d个顶点作为入度,没有与其相邻接的顶点。", i + 1);
}
}
}
采用邻接表表示法创建无向网
#include <stdio.h>
#include <stdlib.h>
#define MVNum 100
typedef int OtherInfo; //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef struct ArcNode
{
int adjvex;
struct ArcNode* nextarc;
OtherInfo info;
}ArcNode; //边结点
typedef struct VNode
{
VerTexType data;
ArcNode* firstarc;
}VNode, AdjList[MVNum]; //表头结点
typedef struct
{
AdjList vertices; //存储所有顶点
int vexnum; //顶点总数
int arcnum; //总边数
}ALGraph; //图的信息
void CreateUDN(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);
int main()
{
ALGraph G = { {'\0',NULL}, 0,0 };
CreateUDN(G);
printALGraph(G);
return 0;
}
//采用邻接表表示法创建无向网
void CreateUDN(ALGraph& G)
{
int i = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
int j = 0;
ArcNode* p1 = NULL;
ArcNode* p2 = NULL;
int w = 0;
printf("请输入无向网的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入无向网的总边数:");
scanf_s(" %d", &G.arcnum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.vertices[i].data));
G.vertices[i].firstarc = NULL; //初始化
}
for (k = 0; k < G.arcnum; k++)
{
printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
printf("请输入第%d条边的权值 : ", k + 1);
scanf_s(" %d", &w, sizeof(OtherInfo));
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (ArcNode*)malloc(sizeof(ArcNode));
p1->adjvex = j;
p1->info = w;
p1->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = p1; //将新结点*p1插入顶点Vi的边表头部
p2 = (ArcNode*)malloc(sizeof(ArcNode));
p2->adjvex = i;
p1->info = w;
p2->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = p2; //将与*p1对称的新的边结点*p2插入顶点Vj的边表头部
}
}
//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
int i = 0;
for (i = 0; i < G.vexnum && (G.vertices[i].data != v); ++i)
{
;
}
return i;
}
//打印邻接表
void printALGraph(ALGraph& G)
{
int i = 0;
ArcNode* pMove = NULL;
for (i = 0; i < G.vexnum; i++)
{
printf("\n第%d个顶点为:%c", i + 1, G.vertices[i].data);
pMove = G.vertices[i].firstarc;
if (pMove)
{
printf("\n与第%d个顶点相邻接的每个顶点在网中的位置(下标值)为:", i + 1);
while (pMove)
{
printf("%d ", pMove->adjvex);
pMove = pMove->nextarc;
}
}
else
{
printf("\n没有与第%d个顶点相邻接的顶点。", i + 1);
}
}
}
采用邻接表表示法创建有向网
#include <stdio.h>
#include <stdlib.h>
#define MVNum 100
typedef int OtherInfo; //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef struct ArcNode
{
int adjvex;
struct ArcNode* nextarc;
OtherInfo info;
}ArcNode; //边结点
typedef struct VNode
{
VerTexType data;
ArcNode* firstarc;
}VNode, AdjList[MVNum]; //表头结点
typedef struct
{
AdjList vertices; //存储所有顶点
int vexnum; //顶点总数
int arcnum; //总边数
}ALGraph; //图的信息
void CreateDN(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);
int main()
{
ALGraph G = { {'\0',NULL}, 0,0 };
CreateDN(G);
printALGraph(G);
return 0;
}
//采用邻接表表示法创建有向网
void CreateDN(ALGraph& G)
{
int i = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
int j = 0;
ArcNode* p1 = NULL;
ArcNode* p2 = NULL;
int w = 0;
printf("请输入有向网的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入有向网的总边数:");
scanf_s(" %d", &G.arcnum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.vertices[i].data));
G.vertices[i].firstarc = NULL; //初始化
}
for (k = 0; k < G.arcnum; k++)
{
printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
printf("请输入第%d条边的权值 : ", k + 1);
scanf_s(" %d", &w, sizeof(OtherInfo));
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (ArcNode*)malloc(sizeof(ArcNode));
p1->adjvex = j;
p1->info = w;
p1->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = p1; //将新结点*p1插入顶点Vi的边表头部
}
}
//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
int i = 0;
for (i = 0; i < G.vexnum && (G.vertices[i].data != v); ++i)
{
;
}
return i;
}
//打印邻接表
void printALGraph(ALGraph& G)
{
int i = 0;
ArcNode* pMove = NULL;
for (i = 0; i < G.vexnum; i++)
{
printf("\n第%d个顶点为:%c", i + 1, G.vertices[i].data);
pMove = G.vertices[i].firstarc;
if (pMove)
{
printf("\n将第%d个顶点作为出度,与其相邻接的每个顶点在网中的位置(下标值)为:", i + 1);
while (pMove)
{
printf("%d ", pMove->adjvex);
pMove = pMove->nextarc;
}
}
else
{
printf("\n将第%d个顶点作为出度,没有与第%d个顶点相邻接的顶点。", i + 1);
}
}
}
创建有向网的逆邻接表
#include <stdio.h>
#include <stdlib.h>
#define MVNum 100
typedef int OtherInfo; //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef struct ArcNode
{
int adjvex;
struct ArcNode* nextarc;
OtherInfo info;
}ArcNode; //边结点
typedef struct VNode
{
VerTexType data;
ArcNode* firstarc;
}VNode, AdjList[MVNum]; //表头结点
typedef struct
{
AdjList vertices; //存储所有顶点
int vexnum; //顶点总数
int arcnum; //总边数
}ALGraph; //图的信息
void CreateDN(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);
int main()
{
ALGraph G = { {'\0',NULL}, 0,0 };
CreateDN(G);
printALGraph(G);
return 0;
}
//创建有向网的逆邻接表
void CreateDN(ALGraph& G)
{
int i = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
int j = 0;
ArcNode* p1 = NULL;
ArcNode* p2 = NULL;
int w = 0;
printf("请输入有向网的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入有向网的总边数:");
scanf_s(" %d", &G.arcnum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.vertices[i].data));
G.vertices[i].firstarc = NULL; //初始化
}
for (k = 0; k < G.arcnum; k++)
{
printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
printf("请输入第%d条边的权值 : ", k + 1);
scanf_s(" %d", &w, sizeof(OtherInfo));
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (ArcNode*)malloc(sizeof(ArcNode));
p1->adjvex = i;
p1->info = w;
p1->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = p1; //将新结点*p1插入顶点Vj的边表头部
}
}
//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
int i = 0;
for (i = 0; i < G.vexnum && (G.vertices[i].data != v); ++i)
{
;
}
return i;
}
//打印逆邻接表
void printALGraph(ALGraph& G)
{
int i = 0;
ArcNode* pMove = NULL;
for (i = 0; i < G.vexnum; i++)
{
printf("\n第%d个顶点为:%c", i + 1, G.vertices[i].data);
pMove = G.vertices[i].firstarc;
if (pMove)
{
printf("\n将第%d个顶点作为入度,与其相邻接的每个顶点在网中的位置(下标值)为:", i + 1);
while (pMove)
{
printf("%d ", pMove->adjvex);
pMove = pMove->nextarc;
}
}
else
{
printf("\n将第%d个顶点作为入度,没有与第%d个顶点相邻接的顶点。", i + 1);
}
}
}
6.4.3 十字链表
采用十字链表表示法创建有向图
//采用十字链表表示法创建有向图
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTEX_NUM 20
typedef int InfoType; //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef struct ArcBox
{
int tailvex;
int headvex;
struct ArcBox* hlink;
struct ArcBox* tlink;
InfoType *info;
}ArcBox;
typedef struct VexNode
{
VerTexType data;
ArcBox *firstin;
ArcBox *firstout;
}VexNode;
typedef struct
{
VexNode xlist[MAX_VERTEX_NUM]; //表头向量
int vexnum; //顶点总数
int arcnum; //总边数
}OLGraph; //图的信息
void CreateOLGraph(OLGraph& G);
int LocateVex(OLGraph& G, VerTexType v);
void printOLGraph(OLGraph& G);
int main()
{
OLGraph G = { {'\0',NULL,NULL}, 0,0 };
CreateOLGraph(G);
printOLGraph(G);
return 0;
}
//采用十字链表表示法创建有向图
void CreateOLGraph(OLGraph& G)
{
int i = 0;
int j = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
ArcBox* p1 = NULL;
printf("请输入有向图的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入有向图的总边数:");
scanf_s(" %d", &G.arcnum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.xlist[i].data));
G.xlist[i].firstin = NULL;
G.xlist[i].firstout = NULL;//初始化
}
for (k = 0; k < G.arcnum; k++)
{
printf("请输入第%d条弧依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
//起点v1是弧尾,终点v2是弧头
//弧<v1,v2>是v1的出度,是v2的入度
i = LocateVex(G, v1);
j = LocateVex(G, v2);
//起点v1是弧尾,下标值为i;终点v2是弧头,下标值为j
//弧<v1,v2>是第i+1个顶点的出度firstout,是第j+1个顶点的入度firstin
p1 = (ArcBox*)malloc(sizeof(ArcBox));
p1->tailvex = i; //起点v1是弧尾,下标值为i
p1->headvex = j; //终点v2是弧头,下标值为j
//p1弧结点中的链域tlink指向与其弧尾tailvext相同的下一条弧(即指向第i+1个顶点v1的下一个出度firstout)
p1->tlink = G.xlist[i].firstout; //p1指向的弧<v1,v2>是第i+1个顶点v1的出度firstout
G.xlist[i].firstout = p1; //前插法将p1插入到第i+1个顶点v1的出度单链表中
//p1弧结点中的链域hlink指向与其弧头headvex相同的下一条弧(即指向第j+1个顶点v2的下一个入度firstin)
p1->hlink = G.xlist[j].firstin; //p1指向的弧<v1,v2>是第j+1个顶点v2的入度firstin
G.xlist[j].firstin = p1; //前插法将p1插入到第j+1个顶点v2的入度单链表中
}
}
//在G的顶点表xlist中获取字符v的下标(数组G.xlist的下标从0开始)
int LocateVex(OLGraph& G, VerTexType v)
{
int i = 0;
for (i = 0; i < G.vexnum && (G.xlist[i].data != v); ++i)
{
;
}
return i;
}
//打印十字链表
void printOLGraph(OLGraph& G)
{
int i = 0;
ArcBox* pMoveIn = NULL;
ArcBox* pMoveOut = NULL;
for (i = 0; i < G.vexnum; i++)
{
printf("\n第%d个顶点为:%c", i + 1, G.xlist[i].data);
pMoveOut = G.xlist[i].firstout;
if (pMoveOut)
{
printf("\n将第%d个顶点作为出度,与其相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
while (pMoveOut)
{
printf("%d ", pMoveOut->headvex);
pMoveOut = pMoveOut->tlink;
}
}
else
{
printf("\n将第%d个顶点作为出度,没有与其相邻接的顶点。", i + 1);
}
pMoveIn = G.xlist[i].firstin;
if (pMoveIn)
{
printf("\n将第%d个顶点作为入度,与其相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
while (pMoveIn)
{
printf("%d ", pMoveIn->tailvex);
pMoveIn = pMoveIn->hlink;
}
}
else
{
printf("\n将第%d个顶点作为入度,没有与其相邻接的顶点。", i + 1);
}
}
}
该有向图的邻接矩阵,其中各行、各列中不为0的元素,与其十字链表每个顶点的出度、入度结果有对应关系。
采用十字链表表示法创建有向网
输入并读取权值,赋值到 弧结点 ArcBox 结构中的 info 成员即可。
//采用十字链表表示法创建有向网
void CreateOLGraph(OLGraph& G)
{
int i = 0;
int j = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
ArcBox* p1 = NULL;
int* w = 0;
printf("请输入有向网的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入有向网的总边数:");
scanf_s(" %d", &G.arcnum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.xlist[i].data));
G.xlist[i].firstin = NULL;
G.xlist[i].firstout = NULL;//初始化
}
for (k = 0; k < G.arcnum; k++)
{
printf("请输入第%d条弧依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
printf("请输入第%d条边的权值 : ", k + 1);
scanf_s(" %d", w, sizeof(InfoType)); //在ArcBox中,info由指向int的指针定义
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (ArcBox*)malloc(sizeof(ArcBox));
p1->tailvex = i;
p1->headvex = j;
p1->info = w; //赋值到弧结点p1中的info成员
p1->tlink = G.xlist[i].firstout;
G.xlist[i].firstout = p1;
p1->hlink = G.xlist[j].firstin;
G.xlist[j].firstin = p1;
}
}
6.4.4 邻接多重表
采用邻接多重表表示法创建无向图
//采用邻接多重表表示法创建无向图
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTEX_NUM 20
typedef enum {unvisited,visited} VisitIf;
typedef int InfoType; //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef struct EBox
{
VisitIf mark;
int ivex;
int jvex;
struct EBox* ilink;
struct EBox* jlink;
InfoType *info;
}EBox;
typedef struct VexBox
{
VerTexType data;
EBox* firstedge;
}VexBox;
typedef struct
{
VexBox adjmulist[MAX_VERTEX_NUM]; //表头向量
int vexnum; //顶点总数
int edgenum; //总边数
}AMLGraph; //图的信息
void CreateAMLGraph(AMLGraph& G);
int LocateVex(AMLGraph& G, VerTexType v);
void printAMLGraph(AMLGraph& G);
int main()
{
AMLGraph G = { {'\0',NULL,NULL}, 0,0 };
CreateAMLGraph(G);
printAMLGraph(G);
return 0;
}
//采用邻接多重表表示法创建无向图
void CreateAMLGraph(AMLGraph& G)
{
int i = 0;
int j = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
EBox* p1 = NULL;
printf("请输入无向图的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入无向图的总边数:");
scanf_s(" %d", &G.edgenum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.adjmulist[i].data));
G.adjmulist[i].firstedge = NULL; //初始化
}
for (k = 0; k < G.edgenum; k++)
{
printf("请输入第%d条弧依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (EBox*)malloc(sizeof(EBox));
p1->ivex = i;
p1->jvex = j;
p1->ilink = G.adjmulist[i].firstedge;
G.adjmulist[i].firstedge = p1;
p1->jlink = G.adjmulist[j].firstedge;
G.adjmulist[j].firstedge = p1;
}
}
//在G的顶点表adjmulist中获取字符v的下标(数组G.xlist的下标从0开始)
int LocateVex(AMLGraph& G, VerTexType v)
{
int i = 0;
for (i = 0; i < G.vexnum && (G.adjmulist[i].data != v); ++i)
{
;
}
return i;
}
//打印邻接多重表
void printAMLGraph(AMLGraph& G)
{
int i = 0;
EBox* pMove = NULL;
for (i = 0; i < G.vexnum; i++)
{
printf("\n第%d个顶点为:%c", i + 1, G.adjmulist[i].data);
pMove = G.adjmulist[i].firstedge;
if (pMove)
{
printf("\n与第%d个顶点相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
while (pMove)
{
if (pMove->ivex == i)
{
printf("%d ", pMove->jvex);
pMove = pMove->ilink;
}
else if (pMove->jvex == i)
{
printf("%d ", pMove->ivex);
pMove = pMove->jlink;
}
}
}
else
{
printf("\n没有与第%d个顶点相邻接的顶点。", i + 1);
}
}
}
采用邻接多重表表示法创建无向网
输入并读取权值,赋值到 边结点 EBox 结构中的 info 成员即可。
//采用邻接多重表表示法创建无向网
void CreateAMLGraph(AMLGraph& G)
{
int i = 0;
int j = 0;
int k = 0;
VerTexType v1 = 0;
VerTexType v2 = 0;
EBox* p1 = NULL;
int* w = 0;
printf("请输入无向网的总顶点数:");
scanf_s(" %d", &G.vexnum);
printf("请输入无向网的总边数:");
scanf_s(" %d", &G.edgenum);
for (i = 0; i < G.vexnum; ++i)
{
printf("请输入第%d个顶点的值:", i + 1);
scanf_s(" %c", &(G.adjmulist[i].data));
G.adjmulist[i].firstedge = NULL; //初始化
}
for (k = 0; k < G.edgenum; k++)
{
printf("请输入第%d条弧依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
printf("请输入第%d条边的权值 : ", k + 1);
scanf_s(" %d", w, sizeof(InfoType)); //在EBox中,info由指向int的指针定义
i = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = (EBox*)malloc(sizeof(EBox));
p1->ivex = i;
p1->jvex = j;
p1->info = w; //赋值到边结点p1中的info成员
p1->ilink = G.adjmulist[i].firstedge;
G.adjmulist[i].firstedge = p1;
p1->jlink = G.adjmulist[j].firstedge;
G.adjmulist[j].firstedge = p1;
}
}