一.概念
在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,成这样的有向图为顶点表示活动的网,简称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;
}