拓扑排序的c语言实现

定义:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

执行步骤:由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。
(1) 选择一个入度为0的顶点并输出之;
(2) 从网中删除此顶点及所有 出边

循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列


#ifndef _queue_h
#define _queue_h
/*定义文件queue.h*/
struct queue;
typedef struct queue *position;

typedef struct queue
{
int element;
position next;
}*queue;

void MakeEmpty(queue Q)
{
Q->next=NULL;
}
void CreateQueue()
{
queue Q;
Q=(struct queue *)malloc((sizeof(struct queue))); 
MakeEmpty(Q);
}

int IsEmpty(queue Q)
{
if(Q->next==NULL)
	return 1;
}
/*入队函数*/
void Enqueue(int n,queue Q)
{
position P;
P=(queue)malloc(sizeof(struct queue));
P->element=n;
P->next=Q->next;
Q->next=P;
}
/*出队*/
int Dequeue(queue Q)
{
position P;
int i;
P=Q->next;
i=P->element;
Q->next=NULL;
free(P);
return i;
}
#endif

#include <stdio.h>
#include <stdlib.h>
#include "queue.h"


typedef struct array/*结构体array->ele[]存储根据拓扑排序排列好的定点*/
{
int ele[5];
}*array;
typedef struct arr/*存储每个定点入度的信息*/
{
int a[5];
}*arr;
typedef struct graph/*存储边的信息*/
{
int edge[5][5];
}*graph;

void Initialize(graph *G,arr *S)
{
(*S)=(arr)malloc(sizeof(struct arr));
int i,j,w;
(*G)=(struct graph *)malloc(sizeof(struct graph));
printf("input");
/*输入每条边,(*G)->edge[][]接受边的信息*/
for(;;)
{	
	scanf("%d%d",&i,&j);	
	if(i!=0&&j!=0)
		(*G)->edge[i][j]=1;
	else break;
}
for(w=1;w<=5;w++)
	(*S)->a[w]=0;
for(j=1;j<=5;j++)
	for(i=1;i<=5;i++)
	{
		if((*G)->edge[i][j]==1)
			(*S)->a[j]+=1;/*每个顶点入度信息*/
	}	
}
void Topsort(graph G,arr S,array *A)
{
queue Q;
(*A)=malloc(sizeof(struct array));
int v,u,n=0,i;
CreateQueue();
for(u=1;u<=5;u++)
{
	if(S->a[u]==0)/*入度为0则入队*/
		Enqueue(u,Q);
}
while(IsEmpty(Q)!=1)
{	
(*A)->ele[n]=Dequeue(Q);
	v=(*A)->ele[n];
	n++;
	for(u=1;u<=5;u++)
		if(G->edge[v][u]==1)
		{	
			S->a[u]-=1;
			if(S->a[u]==0)
				Enqueue(u,Q);
		}
}
}
int main()
{
graph G;
arr S;
array A;
G=NULL;
S=NULL;
A=NULL;
int i;
Initialize(&G,&S);
Topsort(G,S,&A);
for(i=0;i<5;i++)
	printf("%5d",A->ele[i]);
}





程序可以变换的地方:
1.这个程序中的队列也可以改为栈来描述,会简单一些。
2.我用来存储边的信息用的临接矩阵,也可以使用临接链表。
3.存储的信息量可以改变,我把信息都定位为5,大家编辑的时候可以把我的数字都换为maxnum,然后typedef maxnum 你需要的数字

编程值得注意的几点:
1.要了解入度的定义:入度是 图论算法中重要的概念之一。它通常指 有向图中某点作为图中边的终点的次数之和。
2.当下一个函数需要使用上一个函数的参数的值的时候,函数的形參一定要使用双指针,如果你说我是单指针。。。图样图森破,我在结构体定义的时候就已经是指针了。不懂双指针的同学可以看一下这篇文章写的很清楚。http://www.jb51.net/article/37516.htm


最后给大家发一下我的成果吧!
2->3,3->4,3->1,4->5,5->1.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值