拓扑排序
AOV网络 用有向图的顶点表示活动,顶点之间的有向边表示活动间的先后关系,这种有向图称为顶点表示活动网络,简称AOV网络。
当限制各个活动只能串行进行时,可以将AOV网络中所有顶点排列成一个线性序列,且vi必须在vj之前,我们就称这个线性序列为拓扑序列,把对AOV网构造拓扑序列的操作称为拓扑排序。
拓扑排序算法:
1、在网中选择一个入度为0的顶点并输出
2、删除该顶点和所有由它发出的边
3、重复操作,直到没有入度为0的顶点
许多情况下入度为0的顶点不止一个,这样就可以给出多种拓扑排序,且每种都可以保证先后顺序。
邻接矩阵
邻接矩阵中,入度由这个顶点对应列上1的个数决定,所以算法框架为:
1、取1作为第一个新序号
2、找一个没有得到新序号的全0矩阵,若没有则停止寻找,如果所有列都得到了新序号,拓扑排序完成,否则说明有向图中有环存在,无法形成拓扑排序。
3、把新序号赋给找到的列,并将该列对应的顶点输出
4、将找到的列所对应的行置全0
5、新序号+1,重复执行2~5
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef char vertexType;
typedef int edgeType;
typedef struct{
vertexType vexs[100];
edgeType arc[100][100];
int vexnumber,edgenumber;
}MGraph;
void createMGraph(MGraph *G){
int i,j,k,w;
printf("请输入顶点数和边数\n");
scanf("%d,%d",&G->vexnumber,&G->edgenumber); //读取顶点数和边数
for(i=0;i<G->vexnumber;i++){
scanf(&G->vexs[i]);
}
for(i=0;i<G->vexnumber;i++){
for(j=0;j<G->vexnumber;j++){
G->arc[i][j]=-1;
}
}
for(k=0;k<G->vexnumber;k++){
printf("请输入边(vi,vj)的上下标i,j和权值w\n");
scanf("%d,%d,%d",&i,&j,&w);
G->arc[i][j]=w;
G->arc[j][i]=w; //设置对称矩阵
}
}
void topoSortA(MGraph *g,int n){ //用邻接矩阵求拓扑排序
int i,j,k,t,v,D[n];
for(i=0;i<n;i++){
D[i]=0;
}
v=1; //新序号变量置1
for(k=0;k<n;k++){
for(j=0;j<n;j++){ //寻找全0列
if(D[j]==0){
t=1;
for(i=0;i<n;i++){
if(g->arc[i][j]==1){
t=0;
break; //第j列上有1 跳出循环
}
if(t==1){
m=j;
break;
} //找到第j列为全0列
}
}
if(j!=n){
D[m]=v; //将新序号赋给找到的列
printf("%d\t",g->vexs[m]); //输出排序结果
for(i=0;i<n;i++){
g->arc[m][i]=0; //找到的列相应行置全0
v++; //新序号+1
}
}
else break;
}
}
if(v<n) printf("\n The network has a cycle\n");
}
邻接表
typedef char vertexType;
typedef int edgeType;
typedef struct edgenode{ //邻接链表结点
int adjvex;
edgeType weight;
struct edgenode *next; //链域
}edgenode;
typedef struct{
vertexType vertex; //顶点域
egdenode *link; //指针
int id;
}vexnode;
vexnode ga[n]; //顶点表
void topoSortB(vexnode ga[]){
edgenode p;
int i,j,k,m=0,top=-1; //top为栈指针
for(i=0;i<n;i++){ //初始化,建立入度为0的顶点链栈
if(ga[i].id==0){
ga[i].id=top;
top=i;
}
}
while(top!=-1){ //栈非空执行排序
j=top;
top=ga[top].id; //第j+1个顶点退栈
printf("%d\t",ga[j].vertex); //输出退栈顶点
m++; //输出顶点计数
p=ga[j].link;
while(p){ //删去所有以vj+1为起点的边
k=p->adjvex;
ga[k].id--;
if(ga[k].id==0){
ga[k].id=top;
top=k;
}
p=p->next; //找下一条边
}
}
if(m<n) printf("\n The network has a cycle\n");
}