1. 程式人生 > >拓撲排序的c語言實現

拓撲排序的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.