基本思想:
1、在有向图中选一个没有前驱(入度为0)的顶点且输出;
2、从图中删除该顶点和所有以它为尾的边。
重复上述两步,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止(此时说明有向图中存在环)。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*--有向无环图拓扑排序--*/
#define MAX_VERTEX_NUM 20
typedef char VertexType;
typedef int StackElem;
//邻接表存储图
typedef struct ArcNode
{
int adjvex;
struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode
{
int indegree; //图中顶点入度
VertexType data;
ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vertices;
int vernum,arcnum;
}ALGraph;
//创建有向图
int locateVex(ALGraph alg,char v)
{
int i;
for(i=0;i<alg.vernum;i++)
{
if(alg.vertices[i].data == v)
return i;
}
return -1;
}
void createAOVGraph(ALGraph *alg)
{
int i,j,k;
char v1,v2;
ArcNode *p,*s;
printf("输入有向图顶点数个和边数:");
scanf("%d %d",&(alg->vernum),&(alg->arcnum));
getchar();
printf("输入顶点名称\n");
for(k=0;k<alg->vernum;k++)
{
printf("输入第%d个顶点名称:",k);
scanf("%c",&(alg->vertices[k].data));
alg->vertices[k].firstarc = NULL;
alg->vertices[k].indegree = 0;
getchar();
}
printf("输入边信息v1 v2\n");
for(k=0;k<alg->arcnum;k++)
{
printf("输入d第%d条边的起止顶点名称:",k);
scanf("%c %c",&v1,&v2);
i = locateVex(*alg,v1);
j = locateVex(*alg,v2);
p = (ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = j;
p->nextarc = NULL;
if(alg->vertices[i].firstarc == NULL)
{
alg->vertices[i].firstarc = p;
}
else
{
s = alg->vertices[i].firstarc;
while(s->nextarc != NULL)
s = s->nextarc;
s->nextarc = p;
}
alg->vertices[j].indegree += 1; //结点j的入度增加1
getchar();
}
}
//打印有向图
void print(ALGraph G)
{
int i;
ArcNode *p;
printf("图的邻接链表(顶点名称 入度:邻接点)\n");
for(i=0;i<G.vernum;i++)
{
printf("%c %d:",G.vertices[i].data,G.vertices[i].indegree);
p = G.vertices[i].firstarc;
while(p!= NULL)
{
printf("%c ",G.vertices[p->adjvex].data);
p = p->nextarc;
}
printf("\n");
}
printf("\n");
}
//有向图进行拓扑排序,若有向图没有回路则输出图的一个拓扑排序以OK结尾,否则输出序列以error结束
//为避免重复检测入度为0的顶点,设一个栈暂存入度为0的顶点
typedef struct SNode
{
StackElem index;
struct SNode *snext;
}SNode,*PSNode;
typedef struct Stack
{
PSNode top;
PSNode bottom;
}Stack,*PStack;
bool stackEmpty(PStack ps)
{
if(ps->bottom == ps->top)
return true;
return false;
}
PStack initStack()
{
PStack ps = (PStack)malloc(sizeof(Stack));
PSNode p = (PSNode)malloc(sizeof(SNode));
if(p==NULL && ps ==NULL)
{
printf("initstack error!\n");
exit(-1);
}
p->snext = NULL;
ps->bottom = ps->top = p;
return ps;
}
void push(PStack ps,StackElem index)
{
PSNode p = (PSNode)malloc(sizeof(SNode));
if(p == NULL)
{
printf("push error!\n");
exit(-1);
}
p->index = index;
p->snext = ps->top;
ps->top = p;
}
StackElem pop(PStack ps)
{
if(stackEmpty(ps))
{
printf("stack is NULL\n");
exit(-1);
}
else
{
PSNode p = ps->top;
StackElem index = p->index;
ps->top = p->snext;
free(p);
return index;
}
}
//拓扑排序
void topologicalSort(ALGraph G)
{
printf("拓扑排序序列:");
int i,count=0,index; //count对栈中输出顶点计数
ArcNode *p;
StackElem k;
PStack ps = initStack();
for(i=0;i<G.vernum;i++)
{
if(G.vertices[i].indegree==0) //入度为0的顶点入栈
push(ps,i);
}
while(!stackEmpty(ps))
{
index = pop(ps);
printf("%c ",G.vertices[index].data);
++count;
for(p=G.vertices[index].firstarc;p!=NULL;p=p->nextarc)
{
k = p->adjvex;
if((--G.vertices[k].indegree)==0) //对第index个顶点的每个邻接点的入度减1,若邻接点入度为0,则入栈
push(ps,k);
}
}
printf("\n");
if(count < G.vernum)
printf("有向图中存在环ERROR!\n");
else
printf("OK!\n");
}
int main()
{
ALGraph alg;
createAOVGraph(&alg);
print(alg);
topologicalSort(alg);
return 0;
}