//拓扑排序
#include<stdio.h>
#include<malloc.h>
#define NULL 0
#define MAX 20
typedef struct arcnod //表结点定义
{
int adjvex;
struct arcnod *nextarc;
}arcnode;
typedef struct vnode //表头结点类型
{
int data; //定点信息
int indegree; //该点的入度
arcnode *firstarc; //指向第一个表节点
}vnode,adjlist[MAX];
typedef struct
{
adjlist vertices;
int vexnum,arcnum; //图的顶点和边的个数
int kind; //图的类型
}graph; //定义一个邻接表的存储结构
typedef struct //定义一个栈的结构
{
int *top;
int *base;
int nowsize;
}stack;
int emptystack(stack &s) //判断栈是否为空的函数
{
if(s.nowsize==0)return 1;
else return 0;
}
void initstack(stack &s) //构造一个空栈的函数
{
s.base=s.top=(int *)malloc(MAX*sizeof(int));
s.nowsize=0;
}
void pushstack(stack &s,int e) //入栈
{
*s.top=e;
s.top++;
s.nowsize++;
}
void popstack(stack &s,int &e) //出栈
{
e=*(--s.top);
s.nowsize--;
}
int location(graph G,int n) //找出值为n的顶点在存储矩阵中的索引
{
int i;
for(i=0;i<G.vexnum;++i)
{
if(n==G.vertices[i].data)return i;
}
return -1; //无匹配值时返回-1
}
//构造有向图的函数
void creatDG(graph &G)
{
int i,n,k;
arcnode *p1,*p2;
printf("输入顶点和边的个数:/n");
scanf("%d%d",&G.vexnum,&G.arcnum);
printf("输入各顶点的值:/n");
for(i=0;i<G.vexnum;++i)
{scanf("%d",&G.vertices[i].data);}
for(i=0;i<G.vexnum;++i)
{
printf("输入与%d关联的顶点:",G.vertices[i].data);
scanf("%d",&n);
if(n==-1){G.vertices[i].firstarc=0;continue;}
k=location(G,n);
p1=(arcnode *)malloc(sizeof(arcnode));
p1->adjvex=k;
p1->nextarc=0;
G.vertices[i].firstarc=p1;
printf("输入与%d关联的顶点:",G.vertices[i].data);
scanf("%d",&n);
k=location(G,n);
while(n!=-1)
{
p2=(arcnode *)malloc(sizeof(arcnode));
p2->adjvex=k;
p2->nextarc=0;
p1->nextarc=p2;
p1=p2;
printf("输入与%d关联的顶点:",G.vertices[i].data);
scanf("%d",&n);
k=location(G,n);
}
}
}
//计算图中各个顶点的入度并赋值给该顶点的indegree
void findindegree(graph &G)
{
int i,j;
arcnode b1;
arcnode *p1=&b1,*p2;
for(i=0;i<G.vexnum;++i)
G.vertices[i].indegree=0; //初始化各个节点的入度为0
for(i=0;i<G.vexnum;++i)
{
p1=G.vertices[i].firstarc;
while(1)
{
if(p1)
{G.vertices[p1->adjvex].indegree++;
p1=p1->nextarc;
}
if(p1==0)break; //如果到了尾链,则选择下一个头节点开始
}
}
}
//输出图中各个顶点的入度的函数
void print(graph G)
{
for(int i=0;i<G.vexnum;++i)
printf("顶点%d的入度是 %d/n",G.vertices[i].data,G.vertices[i].indegree);
}
//拓扑排序算法
int topo(graph &G)
{
int i,count,k,n;
arcnode *p;
stack s;
findindegree(G);
initstack(s);
for(i=0;i<G.vexnum;++i)
if(G.vertices[i].indegree==0)pushstack(s,i);
count=0;
while(!emptystack(s))
{
popstack(s,n);
printf("%d ",G.vertices[n].data);
++count;
for(p=G.vertices[n].firstarc;p;p=p->nextarc)
{
k=p->adjvex;
if(!(--(G.vertices[k].indegree)))pushstack(s,k);
}
}
if(count<G.vexnum)return 0; //说明此图为有环
else return 1;
}
void main()
{
int i;
graph g;
creatDG(g);
findindegree(g);
print(g);
i=topo(g);
if(i==0)printf("此有向图有环./n");
}