定义
在一个有向图中找一个拓扑序列的过程称为拓扑排序
拓扑排序: 设 G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列v1,v2,…,vn,称为一个拓扑序列。
方法
拓扑排序方法如下:
- 从有序图中选择一个没有前驱(即入度为0)的顶点并且输出它。
- 从图中删去该顶点,并且删去从该顶点发出的全部有向边。
- 重复上述两步,直到剩余的图中不再存在没有前驱的结点为止。
这样操作的结果有两种:一种是图中全部顶点都被输出,即该图中所有顶点都在去拓扑序列中,这说明图中不存在回路;另一种就是图中顶点未被全部输出,这说明图中存在回路。所以可以通过对一个有向图进行拓扑排序,看是否产生全部顶点的拓扑序列来确定该图中是否存在回路问题。
对于给定的有向图,可以采用邻接表作为存储结构,邻接表定义中的VNode类型修改如下:
typedef struct
{
Vertex data; //顶点信息
int count; //增加数据域:存放顶点入度
ArcNode * firstarc; //指向第一个邻接点
}VNode; //头结点类型
对应的拓扑排序算法如下:
void TopSort(AdjGraph *G) //拓扑排序算法
{ int i,j;
int St[MAXV].top=-1; //栈St的指针为top
ArcNode *p;
for(i=0;i<G->n;i++) //入度置初值0
G->adjlist[i].count=0;
for(i=0;i<G->n;i++) //求多有顶点的入度
{
p=G->adjlist[i].firstarc;
while(p!=NULL)
{
G->adjlist[p->adjvex].count++;
p=p->nextarc;
}
}
for(i=0;i<G->n;i++) //将入度为0的顶点进栈
if(G->adjlist[i].count==0)
{
top++;
St[top]=i;
}
while(top>-1) //栈空不循环
{
i=St[top];top==; //出栈一个顶点i
printf("%d",i); //输出该顶点
p=G->adjlist[i].count; //找第一个邻接点
while(p!=NULL) //将顶点i的出边邻接点的入度减1
{
j=p->adjvex;
G->adjlist[j].count--;
if(G->adjlist[j].count==0) // 将入度为0的邻接点进栈
{
top++;
St[top]=j;
}
p=p->nextarc; //找下一个邻接点
}
}