输入有向图的数据,输出该有向图的拓扑序列


#include "stdio.h"
#include "stdlib.h"
#define MAXNUM 100
//两全局变量提供拓扑排序使用
int visited[MAXNUM];
int inDegree[MAXNUM];

/*输入有向图的数据,输出该有向图的拓扑序列
test data 5 4 0 4 2 4 3 3 1 0 3 2 0 2 3 2 1 0 1 -1 -1
input V4 V2 V0 V3 V1
*/
//有向图的结构体
typedef struct
{
int vexnum;
int arcs[MAXNUM][MAXNUM];
}MGraph,*PMGraph;

void initGraph(PMGraph *p)
{
int n,i,j;
*p =(PMGraph)malloc(sizeof(MGraph));
scanf("%d",&n);
//判定N
(*p)->vexnum=n;
//初始化矩阵
for(i=0;i<n;i++)for(j=0;j<n;j++)(*p)->arcs[i][j]=0;
scanf("%d%d",&i,&j);
while(i!=-1&&j!=-1){
(*p)->arcs[i][j]=1;
scanf("%d%d",&i,&j);
}
}
//我的拓扑排序
void topSort(PMGraph p,int i,int *count)
{
//输出变量结果
int j;
printf("V%d ",i);
//标示i节点已访问
visited[i]=1;
//改变输出后的节点入度信息 即去掉i到j的度
for(j=0;j<p->vexnum;j++)
{
if(p->arcs[i][j]==1)inDegree[j]--;
if(!visited[j]&&inDegree[j]==0)
{
*count++;
topSort(p,j,count);
}
}
}
void topTraver(PMGraph p)
{
int i,j;
int count=0;//判定是否有环
//初始化全局变量
for(i=0;i<p->vexnum;i++)
{
visited[i]=0;inDegree[i]=0;
}
//计算每个节点的入度
for(i=0;i<p->vexnum;i++)
{
for(j=0;j<p->vexnum;j++)
{
if(p->arcs[j][i]==1)inDegree[i]++;
}
}
for(i=0;i<p->vexnum;i++)
{
if(!visited[i]&&inDegree[i]==0)
{
count++;
topSort(p,i,&count);
}
}
if(count<p->vexnum)printf("youhuan\n");
}
//北大老师的拓扑排序 能判定图中有环
void topSort1(PMGraph g)
{
int s=-1,i,j,count=0;
//初始化全局变量
for(i=0;i<g->vexnum;i++)
{
visited[i]=0;inDegree[i]=0;
}
//计算每个节点的入度
for(i=0;i<g->vexnum;i++)
{
for(j=0;j<g->vexnum;j++)
{
if(g->arcs[j][i]==1)inDegree[i]++;
}
}
//通过count判定图中是否有环 紧紧判定入度的节点都大于0,是不合适的 例如 4 0 1 1 2 2 3 3 1 -1 -1
for(i=0;i<g->vexnum;i++)
if(inDegree[i]==0)
{
inDegree[i]=s;
s=i;
}
while(s!=-1)//s为访问节点值
{
printf("V%d ",s);
count++;
i=s;
s=inDegree[s];
//访问节点过后,相邻节点入度减一
for(j=0;j<g->vexnum;j++)
if(g->arcs[i][j])
{
inDegree[j]--;
if(inDegree[j]==0)
{
inDegree[j]=s;s=j;
}
}
}
printf("count=%d\n",count);
if(count<g->vexnum)printf("有环\n");
}
void main()
{
PMGraph p;
initGraph(&p);
//topSort1(p);
topTraver(p);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值