一、实验目的
1.掌握图的存储结构。
2.掌握图的拓扑排序方法。
二、实验预习
邻接表、拓扑排序算法。
三、实验内容
编写一个程序,判断如下有向图是否是有向无环图,并给出一个拓扑排序序列。
代码实现
#include <stdio.h>
#include <stdlib.h>
#define MAXVEX 100 // 最大顶点数
typedef struct EdgeNode { // 边表结点
int adjvex; // 邻接点域,存储该顶点对应的下标
int weight; // 权值
struct EdgeNode *next; // 链域,指向下一个邻接点
} EdgeNode;
typedef struct VertexNode { // 顶点表结点
int in; // 顶点入度
char data; // 顶点域,存储顶点信息
EdgeNode *firstedge; // 边表头指针
} VertexNode, AdjList[MAXVEX];
typedef struct { // 图结构
AdjList adjList;
int numVertexes, numEdges; // 图中当前顶点数和边数
} GraphAdjList;
// 建立图的邻接表结构
void CreateALGraph(GraphAdjList *G) {
int i, j, k;
EdgeNode *e;
printf("请输入顶点数和边数:\n");
scanf("%d%d", &G->numVertexes, &G->numEdges);
getchar(); // 吸收回车符
printf("请输入各个顶点的信息:\n");
for (i = 0; i < G->numVertexes; i++) {
scanf("%c", &G->adjList[i].data);
G->adjList[i].in = 0; // 初始化入度为0
G->adjList[i].firstedge = NULL; // 初始化邻接表为空
getchar(); // 吸收回车符
}
printf("请输入各个边的信息:\n");
for (k = 0; k < G->numEdges; k++) {
printf("请输入边(vi, vj)的顶点序号:\n");
scanf("%d%d", &i, &j);
e = (EdgeNode *)malloc(sizeof(EdgeNode));
e->adjvex = j;
e->next = G->adjList[i].firstedge;
G->adjList[i].firstedge = e;
G->adjList[j].in++; // 对应顶点的入度加1
}
}
// 拓扑排序
int TopologicalSort(GraphAdjList *G) {
int i, k, count = 0;
int top = -1; // 栈顶指针
int *stack; // 存储入度为0的顶点
stack = (int *)malloc(G->numVertexes * sizeof(int));
for (i = 0; i < G->numVertexes; i++) {
if (G->adjList[i].in == 0) { // 将入度为0的顶点入栈
stack[++top] = i;
}
}
while (top != -1) { // 栈不为空
k = stack[top--]; // 出栈
printf("%c ", G->adjList[k].data); // 输出拓扑序列
count++; // 统计输出顶点数
for (EdgeNode *e = G->adjList[k].firstedge; e; e = e->next) {
int j = e->adjvex;
if (--G->adjList[j].in == 0) { // 将入度为0的顶点入栈
stack[++top] = j;
}
}
}
if (count < G->numVertexes) { // 输出的顶点数小于图中顶点数,说明存在环
return 0;
} else {
return 1;
}
}
int main() {
GraphAdjList G;
CreateALGraph(&G);
if (!TopologicalSort(&G)) {
printf("该图存在环路!\n");
}
return 0;
}