在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,成这样的有向图为顶点表示活动的网,简称AOV网(activity on vertex network)。最典型的例子是课程与课程之间的优先关系。
若某个AOV网中所有顶点都在拓扑序列中,说明该AOV网不存在回路。一个AOV网的拓扑序列可能不唯一。
对AOV网进行拓扑排序的基本思想是:
(1)从AOV网中选择一个没有前驱的顶点输出它;
(2)从AOV网中删去该顶点,并且删去所有以该顶点为尾的弧;
(3)重复上述两步,直到全部顶点都被输出,或AOV网中不存在没有前驱的顶点。
显然,拓扑排序的结果有两种:AOV网中全部顶点都被输出,这说明AOV网中不存在回路;AOV网中顶点未被全部输出,剩余的顶点均不存在没有前驱的顶点,这说明AOV网中存在回路。
存储结构:
因为拓扑排序过程中需要查找所有以某个顶点为尾的弧,即需要找到该顶点的所有出边,所以,图应该采用邻接表存储。另外在拓扑排序过程中,需要对某顶点的入度进行操作,比如,查找入度等于零的顶点,将某顶点的入度减1等。而在一般图的邻接表对顶点入度的操作不方便,所以在顶点表中增加一个入度域,以方便对入度的操作。
#include <stdio.h> #include <malloc.h> #define MaxNode 26 struct EdgeNode{ int adjVertex; struct EdgeNode* next; }; struct VertexNode{ int in; char data; struct EdgeNode* firstEdge; }; struct ALGraph{ struct VertexNode adjList[MaxNode]; int vertexAmount; int edgeAmount; }; void initialize(struct ALGraph* graph, int vertexAmount, int edgeAmount){ graph->vertexAmount = vertexAmount; graph->edgeAmount = edgeAmount; int i = 0; for(i = 0; i < MaxNode; i++){ graph->adjList[i].in = 0; graph->adjList[i].data = 'A' + i; graph->adjList[i].firstEdge = NULL; } } void addEdge(struct ALGraph* graph, char prev, char next){ struct EdgeNode* edgeNode = (struct EdgeNode*)malloc(sizeof(struct EdgeNode)); edgeNode->adjVertex = next - 'A'; edgeNode->next = NULL; int vertex = prev - 'A'; if(graph->adjList[vertex].firstEdge == NULL){ graph->adjList[vertex].firstEdge = edgeNode; } else { struct EdgeNode* tEdgeNode = graph->adjList[vertex].firstEdge; while(tEdgeNode->next != NULL){ tEdgeNode = tEdgeNode->next; } tEdgeNode->next = edgeNode; } graph->adjList[next - 'A'].in++; } void topSort(struct ALGraph graph){ char outstr[MaxNode]; int k = -1; int count = 0; int queue[MaxNode] = {0}; int front = 0; int rear = -1; int i = 0; for(i = 0; i < graph.vertexAmount; i++){ if(0 == graph.adjList[i].in){ queue[++rear] = i; } } while(rear >= front){ int vertexIndex = queue[front]; outstr[++k] = graph.adjList[vertexIndex].data; struct EdgeNode* adjEdge = graph.adjList[vertexIndex].firstEdge; while(adjEdge){ int tadjVex = adjEdge->adjVertex; graph.adjList[tadjVex].in--; count++; if(graph.adjList[tadjVex].in == 0){ queue[++rear] = tadjVex; } adjEdge = adjEdge->next; } front++; } outstr[++k] = '\0'; if(count < graph.vertexAmount){ printf("%s\n", "circle exist!"); } else { printf("%s\n", outstr); } }; int main(){ freopen("testData.txt", "r", stdin); int vertexAmount; int edgeAmount; while(scanf("%d%d", &vertexAmount, &edgeAmount)){ if(0 == vertexAmount && 0 == edgeAmount){ break; } getchar();/*eat the '\n'*/ /*initialize*/ struct ALGraph graph; initialize(&graph, vertexAmount, edgeAmount); int i = 0; for(i = 0; i < edgeAmount; i++){ char prev = getchar(); char next = getchar(); getchar();/*eat the '\n'*/ addEdge(&graph, prev, next); } topSort(graph); } return 0; }