上一篇文章中讲述了用邻接矩阵存储的图的拓扑排序,下面本文介绍用邻接表存储的图的拓扑排序。
关于拓扑排序的概念及基本思想,我在上一篇文章中已经较为详细的描述了,这里不在介绍。我们知道利用邻接矩阵进行拓扑排序时,程序实现较为简单,但是效率不高,算法的复杂度为O(n^3).而利用邻接表会使入度为0的顶点的操作简化,从而提高算法的效率。
在邻接表存储结构中,为了便于检查每个顶点的入度,可在顶点表中增加一个入度域(id),这样的邻接表如下图所示,这样只需对由n个元素构成的顶点表进行检查就能找出入度为0的顶点。为了避免对每个入度为0的顶点重复访问,可用一个链栈来存储所有入度为0的顶点。在进行拓扑排序前,只要对顶点表进行一次扫描,便可将所有入度为0的顶点都入栈,以后每次从栈顶取出入度为0的顶点,并将其输出。
原始图为:
其对应的邻接表为:
在邻接表存储结构中实现拓扑排序算法的步骤为:
(1) 扫描顶点表,将入度为0的顶点入栈。
(2) 当栈非空时执行以下操作:
1.将栈顶顶点vi的序号弹出,并输出之;
2.检查vi的出边表,将每条出边表邻接点域所对应的顶点的入度域值减1,若该顶点入度为0,则将其入栈;
(3) 若输出的顶点数小于n,则输出“有回路”,否则拓扑排序正常结束。
在具体实现时,链栈无须占用额外空间,只需利用顶点表中入度域值为0的入度域来存放链栈的指针(即指向下一个存放链栈指针的单元的下标),并用一个栈顶指针top指向该链栈的顶部即可。由此给出以下的具体算法:
#include<stdio.h>
#include<stdlib.h>
#define N 7//顶点个数
//邻接表的结构体
typedef struct Node
{
int adjvex;
struct Node *next;
}edgenode;
typedef struct
{
char vertex;
int id;
edgenode *link;
}vexnode;
//进行拓扑排序
void TopoSort_AdjTable(vexnode ga[N])
{
int i,j,k,m=0,top=-1;
edgenode *p;
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;//出栈
printf("%c",ga[j].vertex);
m++;
p=ga[j].link;
while(p)//删除该节点的所有出边
{
k=p->adjvex-1;
ga[k].id--;
if(ga[k].id==0)//将入度为0的顶点入栈
{
ga[k].id=top;
top=k;
}
p=p->next;
}
}
if(m<N)//当输出的顶点数小于N时,说明有环存在
printf("该图存在环!");
}
void main()
{
vexnode ga[N];
char vertex[N]={'A','B','C','D','E','F','G'};
int ID[N]={0,1,2,0,1,1,3};
for(int i=0;i<N;i++)
{
ga[i].vertex=vertex[i];
ga[i].id=ID[i];
}//初始化顶点表
edgenode *s;
//初始化边表
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=2;
ga[0].link=s;
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=3;
ga[0].link->next=s;
s->next=NULL;
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=6;
ga[1].link=s;
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=7;
ga[1].link->next=s;
s->next=NULL;
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=7;
ga[2].link=s;
s->next=NULL;
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=3;
ga[3].link=s;
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=5;
ga[3].link->next=s;
s->next=NULL;
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=7;
ga[4].link=s;
s->next=NULL;
ga[5].link=NULL;
ga[6].link=NULL;
//初始化边表结束
TopoSort_AdjTable(ga);//进行拓扑排序
printf("\n");
}
注:如果程序出错,可能是使用的开发平台版本不同,请点击如下链接: 解释说明
原文:http://blog.csdn.net/tengweitw/article/details/17304311
作者:nineheadedbird