1. 程式人生 > >6-1 Topological Sort (25 分)

6-1 Topological Sort (25 分)

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;
}