定义:对一个有向无环图(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.