#include <stdio.h> #include <string.h> #include <stdbool.h> #include <stdlib.h> //使用卡恩算法(Kahn)和深度优先算法(DFS)实现 //拓扑排序和逆拓扑排序 //拓扑排序和逆拓扑排序顶点顺序相反 //图,邻接矩阵存储 #define MaxVertexNum 100 //最大顶点数 typedef struct { int vex[MaxVertexNum]; //顶点表 int edge[MaxVertexNum][MaxVertexNum]; //边表 int vernum, arcnum; //记录当前图的顶点数量和边数 } MGraph; int vexIndex(MGraph G, int x); void visit(int i); //初始化图 MGraph InitMgraph() { MGraph graph; memset(graph.edge, 0, sizeof(graph.edge)); graph.arcnum = 0; graph.vernum = 0; return graph; } //带头节点 //链队列节点 typedef struct Linknode { int data; struct Linknode *next; } Linknode; //链队列 typedef struct { //队头指针 Linknode *front; //队尾指针 Linknode *rear; } LinkQueue; //初始化队列 void InitQueue(LinkQueue *Q) { //创建头结点 Linknode *temp = (Linknode *) malloc(sizeof(Linknode)); Q->front = temp; Q->rear = temp; } //入队 void EnQueue(LinkQueue *Q, int data) { //创造节点 Linknode *temp = (Linknode *) malloc(sizeof(Linknode)); //赋值 temp->data = data; temp->next = NULL; //连接插入节点 Q->rear->next = temp; //队尾指针更换 Q->rear = temp; } //出队 bool DeQueue(LinkQueue *Q, int *e) { //队列为空 if (Q->rear == Q->front) { return false; } //要出队的节点 Linknode *temp = Q->front->next; *e = temp->data; //队头指针更换 Q->front->next = temp->next; free(temp); //最后一个节点出队 if (temp == Q->rear) { //队尾指针更换 Q->rear = Q->front; } return true; } / //借助队列实现拓扑排序 //卡恩算法 bool TopologicalSort(MGraph G) { //初始化队列 LinkQueue *linkQueue = (Linknode *) malloc(sizeof(linkQueue)); InitQueue(linkQueue); //当前顶点的入度 int indegree[G.vernum]; //记录拓扑排序 int print[G.vernum]; memset(indegree, 0, sizeof(indegree)); //初始化入度数组 for (int i = 0; i < G.vernum; ++i) { for (int j = 0; j < G.vernum; j++) { if (G.edge[j][i] == 1) { indegree[i]++; } } } //初始化print数组 memset(print, -1, sizeof(print)); //度为0的顶点索引入队列 for (int i = 0; i < G.vernum; i++) { if (indegree[i] == 0) { EnQueue(linkQueue, i); indegree[i] = -1; } } //记录顶点个数 int count = 0; int *e = malloc(sizeof(int)); while (linkQueue->rear != linkQueue->front) { DeQueue(linkQueue, e); print[count] = G.vex[*e]; count++; for (int i = 0; i < G.vernum; ++i) { if (G.edge[*e][i] == 1) { indegree[i]--; } if (indegree[i] == 0) { EnQueue(linkQueue, i); indegree[i] = -1; } } } if (count < G.vernum) return false; else { for (int i = 0; i < G.vernum; i++) { printf("%d ", print[i]); } return true; } } int time; int finalTime[100]; int visited[100]; //DFS算法实现拓扑排序 //v为入度为0的顶点 void DFSTopologicalSort(MGraph G, int i) { //对i做已访问标记 visited[vexIndex(G, i)] = 1; //找到i的所有邻接点 for (int j = 0; j < G.vernum; j++) { if (visited[j] == 0 && G.edge[vexIndex(G, i)][j] == 1) { DFSTopologicalSort(G, G.vex[j]); } } (time)++; finalTime[vexIndex(G, i)] = time; } //使用后visited会被重新赋值,需重置 //建议用一个变量临时保存原有图 void DFSTraverseTopologicalSort(MGraph G, int i) { time = 0; for (int j = 0; j < G.vernum; j++) { visited[j] = 0; } DFSTopologicalSort(G, i); for (int j = 0; j < G.vernum; j++) { if (visited[j] == 0) { DFSTopologicalSort(G, G.vex[j]); } } for (int j = 0; j < G.vernum; j++) { printf("%d ", finalTime[j]); } } //有向图深度优先搜索 void niDFSTopologicalSort(MGraph G, int i) { //对i做已访问标记 visited[vexIndex(G, i)] = 1; //找到i的所有邻接点 for (int j = 0; j < G.vernum; j++) { if (visited[j] == 0 && G.edge[vexIndex(G, i)][j] == 1) { niDFSTopologicalSort(G, G.vex[j]); } } printf("%d ", i); } //使用后visited会被重新赋值,需重置 //建议用一个变量临时保存原有图 //连通图和非连通图的深度优先搜索(改进) void niDFSTraverseTopologicalSort(MGraph G, int i) { for (int j = 0; j < G.vernum; j++) { visited[j] = 0; } niDFSTopologicalSort(G, i); for (int j = 0; j < G.vernum; j++) { if (visited[j] == 0) { niDFSTopologicalSort(G, G.vex[j]); } } } int main(void) { //有向图 //初始化图 MGraph graph = InitMgraph(); //图添加元素 //顶点集添加1,2,3,4,5 for (int i = 0; i < 5; i++) { graph.vex[i] = i + 1; graph.vernum++; } //边集加边<1,2>,<1,4>,<2,3>,<2,4>,<3,5>,<4,3>,<4,5> graph.edge[0][1] = 1; graph.edge[0][3] = 1; graph.edge[1][2] = 1; graph.edge[1][3] = 1; graph.edge[2][4] = 1; graph.edge[3][2] = 1; graph.edge[3][4] = 1; graph.arcnum = 7; printf("拓扑排序序列:\n"); TopologicalSort(graph); printf("\n"); printf("tineFinal数组:\n"); DFSTraverseTopologicalSort(graph, 1); printf("\n"); printf("逆拓扑排序序列:\n"); niDFSTraverseTopologicalSort(graph, 5); } //返回x在顶点表的索引 int vexIndex(MGraph G, int x) { int index = -1; for (int i = 0; i < G.vernum; i++) { if (G.vex[i] == x) { index = i; break; } } return index; }
测试用例