首页 > 代码库 > 拓扑排序
拓扑排序
1.AOV网
如果用图中的顶点表示活动,边表示活动之间的先后关系,比如从顶点Vi到Vj之间存在有向边<Vi,Vj>,则表示活动活动Vi必须在活动Vj之前进行,这样用弧表示优先关系的有向图称为顶点表示活动的网(Activity On Vertex NetWork),简称AOV网。
如下图:
说明:AOV网中不含回路,因为存在回路意味着某项活动应以自己为先决条件,显然这是荒谬的。你想嘛,一件事必须等该件事做完了才开始做,那这件事到底什么时候做呢?答案是无穷无尽的等待,死循环。
2.拓扑排序
对于一个AOV网,其所有顶点可以排成一个线性序列Vi1,Vi2,Vi3,...,Vin,该线性序列具有以下性质:如果在AOV网中,从顶点Vi到顶点Vj存在一条路径,则在该序列中顶点Vi一定排在顶点Vj之前,具有这种性质的线性序列称为拓扑序列,构造拓扑序列的操作称之为拓扑排序。
那么如何进行拓扑排序呢?
①在有向图中选取一个没有前驱的顶点并输出
②从图中删除该顶点和所有以它为尾的弧
AOV网,初始状态 |
输出V1之后 |
输出V2之后 |
输出V3之后(V3和V4都满足入度为零的条件,所以先选哪个都没关系) |
输出V4之后 |
3.编码实现
采用邻接表存储有向图:
arcNode结构体存储为以adjvex为弧头的弧的相关信息
vNode存储节点信息并指向第一个出边
topoSequence存储拓扑排序中输出的顶点
findIndegree查找所有顶点的入度:从第0号位置开始查找,遇到以adjvex为弧头的弧对应的indegree就加一,这样查找完后,indegree中就记录了每个顶点的入读
topologicalSort进行拓扑排序
#include<stdio.h> #include<stdlib.h> typedef struct _arcNode { int adjvex; int weight; struct _arcNode *nextarc; }arcNode; typedef struct _vNode { char data; arcNode *firstarc; }vNode; #define MaxVertexNum 100 typedef vNode adjList[MaxVertexNum]; typedef struct _adjGraph { adjList ver; int e, n; }adjGraph; void createAdjGraph(adjGraph *G) { scanf("%d,%d", &G->n, &G->e); getchar(); for (int i = 0; i < G->n; i++) { scanf("%c ", &G->ver[i].data); G->ver[i].firstarc = NULL; } int a, b, w; for (int i = 0; i < G->e; i++) { scanf("%d,%d,%d", &a, &b, &w); arcNode *tmp = (arcNode*)malloc(sizeof(arcNode)); tmp->weight = w; if (G->ver[a].firstarc == NULL) { tmp->adjvex = b; tmp->nextarc = NULL; G->ver[a].firstarc = tmp; } else { tmp->adjvex = b; tmp->nextarc = G->ver[a].firstarc; G->ver[a].firstarc = tmp; } } } typedef struct _topoSequenceS { char data[MaxVertexNum]; int top; }topoSequenceS; topoSequenceS *topoS = (topoSequenceS*)malloc(sizeof(topoSequenceS)); void findInDegree(adjGraph *G, int *indegree) { for (int i = 0; i < G->n; i++) { arcNode *arcPos = G->ver[i].firstarc; while (arcPos != NULL) { indegree[arcPos->adjvex] += 1; arcPos = arcPos->nextarc; } } } void topologicalSort(adjGraph *G) { int *indegree = (int*)malloc(sizeof(int)*G->n); for (int i = 0; i < G->n; i++) indegree[i] = 0; findInDegree(G, indegree); int *tmpS = (int*)malloc(sizeof(int)*G->n); int top = -1; for (int i = 0; i < G->n; i++) { if (!indegree[i])tmpS[++top] = i; } topoS->top = -1; int i = 0; while (top != -1) { i=topoS->data[++topoS->top] = tmpS[top--]; arcNode *arcPos = G->ver[i].firstarc; while (arcPos != NULL) { if (!(--indegree[arcPos->adjvex]))tmpS[++top] = arcPos->adjvex; arcPos = arcPos->nextarc; } } } #include<conio.h> int main(void) { freopen(".\\in.txt", "r", stdin); adjGraph *G = (adjGraph*)malloc(sizeof(adjGraph)); createAdjGraph(G); fclose(stdin); for (int i = 0; i < G->n; i++) { printf("%c->", G->ver[i].data); arcNode *pos = G->ver[i].firstarc; while (pos != NULL) { printf("%c->", G->ver[pos->adjvex].data); pos = pos->nextarc; } printf("\n"); } topologicalSort(G); if (topoS->top < G->n - 1) printf("Error!There is a circuit!\n"); else { int vexNum = 0; int pos = 0; while (topoS->top != pos-1) { vexNum = topoS->data[pos]; printf("%c\n", G->ver[vexNum].data); pos++; } } getch(); return 0; }
测试文本in.txt:
5,5
A B C D E
0,1,1
1,2,2
1,3,3
2,4,4
3,4,5
测试结果:
拓扑排序