AOV网:顶点表示活动,弧表示活动间关系的有向无环图
拓扑排序即求AOV网的拓扑序列:
- 输出AOV网中所有入度为0的结点
- 将当前结点删除并将其所有邻结点的入度减一,再输出所有入度为0的结点
- 如果输出的结点个数小于图的结点个数,则存在回路,无拓扑序列,否则输出的结点为一个拓扑序列
求图中各个结点入度:设置入度数组记录各个结点入度,遍历图中的所有结点,若当前结点有邻结点,则更新其邻结点入度数组。
拓扑排序:利用栈将所有入度为0的结点进栈。如果栈非空则重复如下操作:
- 栈顶元素出栈并输出
- 将其所有邻结点的入度减一,如果更新后邻结点入度变为0则入栈
最后判断输出个数和图中的结点个数即可
void FindID(Graph G,int indegree[]){//求图中各顶点的入度,并记录在数组
for(int i=0;i<G.vexnum;i++){//初始化入度数组
indegree[i]=0;
}
for(int i=0;i<G.vexnum;i++){//遍历每个结点,若当前结点有邻结点,则更新其邻结点入度数组
ArcNode* p=G.vertex[i].firstarc;
while(p!=NULL){
indegree[p->adjvex]++;
p=p->nextarc;
}
/*邻接矩阵实现:
int w=FirstAdjVex(G,i);
while(w!=-1){
indegree[w]++;
w=NextAdjVex(G,i,w);
}
*/
}
}
void TopSort(Graph G){//拓扑排序,输出图G的拓扑序列
int indegree[MAX_VERTEX_NUM];//入度数组
int count=0;//统计拓扑序列元素个数,小于图的结点个数则不为AOV网
FindID(G,indegree);//求顶点入度
InitStack(&S);//建立并初始化栈S
for(int i=0;i<G.vexnum;i++){//让所有度为0的结点入栈
if(indegree[i]==0){
PUSH(&S,i);
}
}
while(!IsEmpty(S)){//栈非空则栈顶元素出栈并输出
POP(&S,&v);
visit(v);
count++;//更新count值
ArcNode* p=G.vertex[v].firstarc;
while(p!=NULL){//更新其邻结点入度数组,如果度变为0则让其入栈
int k=--indegree[p->adjvex];
if(k==0){
PUSH(&S,p->adjvex);
}
p=p->nextarc;
}
}
if(count<G.vexnum){
printf("该图有回路,不为AOV网无拓扑序列\n");
}
}