6-1 Topological Sort (25 分)
編寫程序以在有向圖中找到拓撲順序。
功能格式:
bool TopSort( LGraph Graph, Vertex TopOrder[] );
其中LGraph
定義如下:
typedef struct AdjVNode *PtrToAdjVNode; struct AdjVNode{ Vertex AdjV; PtrToAdjVNode Next; }; typedef struct Vnode{ PtrToAdjVNode FirstEdge; } AdjList[MaxVertexNum]; typedef struct GNode *PtrToGNode; struct GNode{ int Nv; int Ne; AdjList G; }; typedef PtrToGNode LGraph;
拓撲順序應該被存儲在TopOrder[]
其中,TopOrder[i]
是i
將得到的序列中的第一個頂點。如果圖中有一個循環,則拓撲排序不能成功 - 在這種情況下TopSort
必須返回false
; 否則返回true
。
請注意,拓撲順序可能不是唯一的,但是判斷的輸入保證了結果的唯一性。
法官示例程序:
#include <stdio.h> #include <stdlib.h> typedef enum {false, true} bool; #define MaxVertexNum 10 /* maximum number of vertices */ typedef int Vertex; /* vertices are numbered from 0 to MaxVertexNum-1 */ typedef struct AdjVNode *PtrToAdjVNode; struct AdjVNode{ Vertex AdjV; PtrToAdjVNode Next; }; typedef struct Vnode{ PtrToAdjVNode FirstEdge; } AdjList[MaxVertexNum]; typedef struct GNode *PtrToGNode; struct GNode{ int Nv; int Ne; AdjList G; }; typedef PtrToGNode LGraph; LGraph ReadG(); /* details omitted */ bool TopSort( LGraph Graph, Vertex TopOrder[] ); int main() { int i; Vertex TopOrder[MaxVertexNum]; LGraph G = ReadG(); if ( TopSort(G, TopOrder)==true ) for ( i=0; i<G->Nv; i++ ) printf("%d ", TopOrder[i]); else printf("ERROR"); printf("\n"); return 0; } /* Your function will be put here */
樣本輸入1(對於圖中所示的圖表):
5 7 1 0 4 3 2 1 2 0 3 2 4 1 4 2
樣本輸出1:
4 3 2 1 0
樣本輸入2(對於圖中所示的圖表):
5 8 0 3 1 0 4 3 2 1 2 0 3 2 4 1 4 2
樣本輸出2:
ERROR
bool TopSort( LGraph Graph, Vertex TopOrder[] ) { int Indegree[Graph->Nv];//建立入度表 int Queue[Graph->Nv];//建立隊列存儲入隊為0的節點 int pre=0, tail=0;//隊首和隊尾 PtrToAdjVNode p; for(int i=0; i<Graph->Nv; i++) Indegree[i] = 0;//初始化入度表為0 for(int i=0; i<Graph->Nv; i++){//構造入度表 for(p=Graph->G[i].FirstEdge; p!=NULL; p=p->Next) Indegree[p->AdjV]++; } for(int i=0; i<Graph->Nv; i++){//將入度為0的節點入隊 if(!Indegree[i]) Queue[tail++] = i; } int num = 0;//記錄入隊的數目 while(pre < tail){ int pos = Queue[pre]; TopOrder[num++] = Queue[pre++]; for(p=Graph->G[pos].FirstEdge; p!=NULL; p=p->Next){ int index = p->AdjV; --Indegree[index];//將出隊的節點,即刪除的節點的鄰接節點入隊減1 if(!Indegree[index])//若更新入度后入度為0則入隊 Queue[tail++] = index; } } if(num == Graph->Nv) return true; else return false; }