拓撲排序的c語言實現
阿新 • • 發佈:2019-02-06
定義:對一個有向無環圖(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.