圖的儲存結構——鄰接矩陣與鄰接表

weixin_33866037發表於2017-04-18

1 概述#

簡單的說,圖由表示資料元素的集合V和表示資料之間關係的集合E組成,記為G=<V,E>。圖又分為有向圖與無向圖。下面是圖的一些基本元素:

  • 邊(edge):頂點的序偶。
  • 頂點(vertex):資料元素。
  • 權重(weight):用來表示一個頂點到另一個頂點的距離、代價、耗費等。
  • 度(degree):與該頂點相關聯的邊的數目,入度、出度等等。
4430424-2199a53a6b0f35e5.png
無向圖G1與有向圖G2

圖的基本型別常使用的有相鄰矩陣與鄰接表。下面將從兩方面介紹圖的儲存結構與基本操作。

2 圖的相鄰矩陣儲存型別#

圖的相鄰矩陣或鄰接矩陣表示定點之間的鄰接關係,即表示頂點之間有邊或沒有邊的情況。如下圖則是無向圖G1和有向圖G2的鄰接矩陣。


4430424-acb492b035b82ac9.png
(a)無向圖G1的鄰接矩陣 (b)有向圖G2的鄰接矩陣
  • 相鄰矩陣型別定義

對於有向圖,相鄰矩陣不一定對稱。因為如果相鄰矩陣第i行第j列的元素為1,則表示有一條從頂點vi到頂點vj的弧,而此時不一定存在由頂點vj到頂點vi的弧。

 /*圖的相鄰矩陣儲存型別定義*/
#define MaxVertexNum 100 /*最大頂點數設為100*/
typedef enum{FALSE,TRUE} Boolean;
Boolean mark[MaxVertexNum];

typedef char VertexType; /*頂點型別設為字元型*/
typedef int EdgeType; /*邊的權值設為整型*/

typedef struct {
    VertexType vexs[MaxVertexNum]; /*頂點表*/
    EdgeType edges[MaxVertexNum][MaxVertexNum]; /*鄰接矩陣,即邊表*/
    int numVertex,numEdge; /*頂點數和邊數*/
}Mgragh,*MGragh; /*Maragh 是以鄰接矩陣儲存的圖型別*/
  • 圖建立

首先定義相鄰矩陣的尺寸,即定點數和邊數。
輸入每條邊資訊,vi為初始點,vj為終止點。將鄰接表中的edges[i][j]設定為1,代表起點為i,終點為j,存在一條邊。


void CreateMGraph(MGragh G){/*建立有向圖G 的鄰接矩陣儲存*/
int i,j,k,w;
char ch;
cout<<"請輸入頂點數和邊數";
cin>>i>>j;
G->numVertex=i;
G->numEdge=j;

cout<<"請輸入頂點資訊:"<<endl;

for (i=0;i<G->numVertex;i++) {cout<<"第"<<i<<"個點:";cin>>G->vexs[i];} /*輸入頂點資訊,建立頂點表*/
for (i=0;i<G->numVertex;i++)
    for (j=0;j<G->numVertex;j++) 
        G->edges[i][j]=0; /*初始化鄰接矩陣*/

cout<<"請輸入每條邊對應的兩個頂點的序號:\n";

for (k=0;k<G->numEdge;k++){
    cout<<"v<i,j>:";
    cin>>i>>j; /*輸入e 條邊,建立鄰接矩陣*/
        G->edges[i][j]=1;
            }
}
  • 判斷邊類

FirstEdge即返回以v為頂點的第一條邊。它的想法是:返回以頂點v的編號的相鄰矩陣行,從j=0開始遍歷,直到搜尋到矩陣元素為1時,表示i到j有一條邊,於是返回此條邊。

NextEdge即返回以v為頂點的下一條邊。當輸入邊edge時,將返回以edge.from的編號相同的矩陣行,從j=edge.to+1開始遍歷,直到搜尋到矩陣元素為1時,表示i到j有一條邊,返回此邊。


Edge FirstEdge(MGragh G,int oneVertex){
   Edge myEdge;
   myEdge.from=oneVertex;
   for(int i=0;i<G->numVertex;i++){
       if(G->edges[oneVertex][i]!=0){
           myEdge.to=i;
           myEdge.weight=G->edges[oneVertex][i];
           break;
       }
   }
   return myEdge;
}

Edge NextEdge(MGragh G,Edge preEdge){
   Edge myEdge;
   myEdge.from =preEdge.from ;
   if(preEdge.to <G->numVertex){
       for(int i=preEdge.to+1;i<G->numVertex;i++){
           if(G->edges[preEdge.from][i]!=0){
               myEdge.to =i;
               myEdge.weight =G->edges[preEdge.from ][i];
               break;
           }
       }
   }
   return myEdge;
}

bool isEdge(MGragh G, Edge myEdge){
   int test=0;
   for(int i=0;i<G->numVertex;i++){
       if(myEdge.to>=0&&G->edges[myEdge.from][myEdge.to]==1)return true;
   }
   return false;
}
  • 兩種周遊演算法

以有向圖G2為例:

深度優先搜尋的周遊演算法如下:假設從v0點出發,首先將v0的標誌位設定為TRUE,然後從v0的第一條邊出發,尋找第一條邊的終點v2。因為v2為被訪問過,因此將v2標誌位設定為TRUE。從v2出發,尋找v2的第一條邊終點為v3。因為v3為被訪問過,因此設v3的標誌位為TRUE。從v3出發,尋找v3的第一條邊終點為v0,標誌位為TRUE說明已被訪問過。返回上一個頂點v2,尋找v2的nextEdge,無。返回v0,尋找v0的nextEdge,為v1,標識v1為TRUE。遍歷完畢。

廣度優先演算法的周遊如下:假設從v0出發。首先將v0的標誌位設定為TRUE,將v0入隊。因為佇列不為空,所以取出front,設定為u,同時pop掉front。尋找v0的第一條邊的終點v2。輸出v2,並將其push入佇列;尋找v0的第二條邊的終點v1,,輸出v1,並將其push入佇列;尋找v0的第三條邊的終點,無。返回取出front,將v2設定為u,pop掉它。尋找v2的第一條邊v3,輸出v3並將其push如佇列;尋找v2的第二條邊,無。返回取出front,將v1設定為u,pop掉它。尋找v1的第一條邊,無。返回取出front,將v3設定為u,pop掉它,尋找v3的第一條邊v0,因為以被訪問,因此跳過;尋找v3的第二條邊,無。演算法結束。

//深度優先周遊    
void DFS(MGragh G, int v){
    mark[v]=TRUE;
    cout<<G->vexs[v];
    for(Edge e=FirstEdge(G,v);isEdge(G,e);e=NextEdge(G,e)){
        if(mark[e.to]==FALSE) DFS(G,e.to);
    }
}

void DFSM(MGragh G,int v){
    for(int i=0;i<G->numVertex;i++){
        mark[i]=FALSE;
    }
    DFS(G,0);
}

//廣度優先周遊
void BFS(MGragh G, int v){
    for(int i=0;i<G->numVertex;i++){
        mark[i]=FALSE;
    }
    using std::queue;
    queue<int>Q;
    cout<<G->vexs[v];
    mark[v]=TRUE;
    Q.push(v);
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        for(Edge e=FirstEdge(G,u);isEdge(G,e);e=NextEdge(G,e))
            if(mark[e.to]==FALSE){
                cout<<G->vexs[e.to];
                mark[e.to]=TRUE;
                Q.push(e.to);
            }
    }
}

3 圖的鄰接表儲存型別#

當圖中的邊數較少時,相鄰矩陣就會出現大量的0元素,儲存這些0元素將消耗大量的儲存空間。
鄰接表表示法是一種鏈式儲存結構,由一個順序儲存的頂點表和n個連結串列儲存的邊表組成。頂點表目有兩個域:頂點資料域和指向此頂點邊表指標域。邊表把依附於同一個頂點vi的邊(即相鄰矩陣中同一行的非0元素)組織成一個單連結串列。邊表中的每一個表目都代表一條邊,由兩個主要的域組成:與頂點vi鄰接的另一個頂點的序號、指向邊表中下一個邊表的目的指標。
頂點結點和邊結點的結構如下:

4430424-7ee288f94e9cc47d.png
Paste_Image.png

與鄰接矩陣儲存型別相似,鄰接表的基本函式依然包括FirstEdge,NextEdge和isEdge。這裡不再重複,下面只給出廣度周遊和深度周遊演算法。

  • 鄰接表型別定義
using namespace std;
#define MAX_VERTEXT_NUM 20
typedef enum{FALSE,TRUE} Boolean;
Boolean mark[MAX_VERTEXT_NUM];

typedef struct edge{     /*邊定義*/
    int from,to,weight;
}Edge,*Edged;

typedef struct ArcNode{     /*邊結點定義*/
    int adjvex;
    struct ArcNode *nextArc;
    int weight;
}ArcNode;

typedef struct VNode{     /*頂點定義*/
    char data;
    ArcNode *firstArc;
}VNode, AdjList[MAX_VERTEXT_NUM];

typedef struct Indegree{     /*每個點的入度*/
    int indegree;
}Indegree,indegree[MAX_VERTEXT_NUM];

typedef struct{     /*圖定義*/
    AdjList verTices;
    int vexNum;
    int arcNum;
    int kind;
    indegree Indegree;
}ALGraph;
  • 圖的鄰接表儲存型別建立

首先輸入頂點和邊的個數,同時申請頂點個數的結點空間。
每次輸入邊的鄰接關係時i-j時,首先申請一個邊結點空間給,結點的adjvex為j,nextarc為頭結點firstarc的nextarc,頭結點的firstarc變為此j結點arcnode。

4430424-1447a5d3cdb8aeb7.png
鄰接表插入頂點
void CreateGraph(ALGraph *G)
{
    int i,j,k,weight;
    ArcNode *arcNode;
    printf_s("請輸入頂點數和邊數:");
    cin>>G->vexNum;
    cin>>G->arcNum;
    //建立頂點表
    printf_s("建立頂點表\n");
    for (i = 0; i < G->vexNum; i++)
    {
        printf_s("請輸入第%d個頂點:", i);
        cin>>G->verTices[i].data;
        arcNode = (ArcNode *)malloc(sizeof(ArcNode));
        arcNode->adjvex=i;
        arcNode->nextArc=NULL;
        G->verTices[i].firstArc=arcNode;
        G->Indegree[i].indegree=0;
    }
    //建立邊表
    printf_s("建立邊表\n");
    for (k = 0; k < G->arcNum; k++)
    {
        printf_s("請輸入(vi-vj)的頂點對序號");
        cin>>i;
        cin>>j;
        arcNode = (ArcNode *)malloc(sizeof(ArcNode));
        arcNode->adjvex = j;
        arcNode->nextArc = G->verTices[i].firstArc->nextArc;//插入表頭
        G->verTices[i].firstArc ->nextArc= arcNode;
        G->Indegree[j].indegree++;
    }
}
  • 兩種周遊演算法

深度優先周遊:對於鄰接表儲存型別,它採用遞迴演算法,從起始點v0沿著鄰接表一次訪問,直到next指標為NULL,則返回上一層,進入上一層頂點v1所在的連結串列繼續逐個訪問。

廣度周遊與相鄰矩陣法類似,這裡不做闡述。演算法如下:

//深度優先周遊
void DFSM(ALGraph *G,int i){
    ArcNode *p;
    cout<<G->verTices[i].data;
    mark[i]=TRUE;
    p=G->verTices[i].firstArc;
    while(p){
        if(mark[p->adjvex]==FALSE)
            DFSM(G,p->adjvex);
        p=p->nextArc;       
    }
}

void DFS(ALGraph *G){
    for ( int i=0; i<G->vexNum;i++)
        mark[i]=FALSE;
    for( int i=0; i<G->vexNum;i++)
        if(!mark[i])
            DFSM(G,i);
}

//廣度優先周遊
void BFS(ALGraph *G,int x){
    ArcNode *p;
    int w;
    using std::queue;
    queue<int> Q;
    for ( int i=0; i<G->vexNum;i++) {mark[i]=FALSE;}
    cout<<G->verTices[x].data;
    mark[x]=TRUE;
    Q.push(x);
    while(!Q.empty()){
        int v=Q.front();
        Q.pop();
        p=G->verTices[v].firstArc;
        while(p){
            int w=p->adjvex;
            if(mark[w]==FALSE){
                mark[w]=TRUE;
                cout<<G->verTices[w].data;
                Q.push(w);}
            p=p->nextArc;
            }
        }
}
  • 拓撲排序

有向圖的邊可以看做定點之間制約關係的描述。在工程實踐中,有些工程的進行經常受到一定條件的約束,例如一個工程專案通常由若干子工程組成,某些子工程完成之後另一些子工程才能開始。

一個無環的有向圖稱為有向無環圖,有向無環圖常用來描述一個過程或一個系統的進行過程。對於有向無環圖G=<V,E>,如果頂點序列滿足:存在頂點vi到vj的一條路徑,那麼在序列中頂點vi必在頂點vj之前,頂點集合V的這種線型序列稱作一個拓撲序列。

進行有向圖的拓撲序列方法如下:

  1. 從有向圖中選出一個沒有前驅(入度為0)的頂點並輸出。
  2. 刪除圖中該頂點和所有以它為起點的弧。

不斷重複上述兩個步驟,會出現兩種情形:要麼有向圖中頂點全部被輸出,要麼當前圖中不存在沒有前驅的頂點。當圖中的頂點全部輸出時,就完成了有向無環圖的拓撲排序;當圖中還有頂點沒有輸出時,說明有向圖中含有環。

它的工作思想如下:

4430424-5b64f0f5146aa52a.png
拓撲排序

//拓撲排序
void TopsortbyQueue(ALGraph*G){
    for(int i=0; i< G->vexNum;i++)
        mark[i]=FALSE;
    using std::queue;
    queue<int> Q;
    cout<<"拓撲序列為:"<<endl;
    for(int i=0; i< G->vexNum;i++){
        if(G->Indegree[i].indegree==0)
            Q.push(i);}
        while(!Q.empty()){
            int v=Q.front();
            Q.pop();
            cout<<v;
            mark[v]=TRUE;
            for(Edge e=FirstEdge(G,v);isEdge(G,e);e=NextEdge(G,e)){
                G->Indegree[e.to].indegree--;
                if(G->Indegree[e.to].indegree ==0)
                    Q.push(e.to);
            }
        }
        for(int i=0;i< G->vexNum;i++)
            if(mark[i]==FALSE){
                cout<<endl;
                cout<<"還有頂點未訪問,此圖有環。"<<endl;
                break;
            }
}

4 總結#

明顯感覺到寫得多了對於語言的運用更熟練了,也更有了設計演算法需要的邏輯思想。這個寫的還算比較順隨著思維和語言能力提升,希望能在acm校選賽比賽上有好的發揮過兩天來更新結果!

5 附錄#

鄰接矩陣:

4430424-bab657e9627a4b5c.png
鄰接矩陣測試結果
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<queue> 
using namespace std;

#define MaxVertexNum 100 /*最大頂點數設為100*/
typedef enum{FALSE,TRUE} Boolean;
Boolean mark[MaxVertexNum];

typedef char VertexType; /*頂點型別設為字元型*/
typedef int EdgeType; /*邊的權值設為整型*/

typedef struct {
    VertexType vexs[MaxVertexNum]; /*頂點表*/
    EdgeType edges[MaxVertexNum][MaxVertexNum]; /*鄰接矩陣,即邊表*/
    int numVertex,numEdge; /*頂點數和邊數*/
}Mgragh,*MGragh; /*Maragh 是以鄰接矩陣儲存的圖型別*/


typedef struct edge{
    int from,to,weight;
}Edge,*Edged;

void CreateMGraph(MGragh G){/*建立有向圖G 的鄰接矩陣儲存*/
int i,j,k,w;
char ch;
cout<<"請輸入頂點數和邊數";
cin>>i>>j;
G->numVertex=i;
G->numEdge=j;

cout<<"請輸入頂點資訊:"<<endl;

for (i=0;i<G->numVertex;i++) {cout<<"第"<<i<<"個點:";cin>>G->vexs[i];} /*輸入頂點資訊,建立頂點表*/
for (i=0;i<G->numVertex;i++)
    for (j=0;j<G->numVertex;j++) 
        G->edges[i][j]=0; /*初始化鄰接矩陣*/

cout<<"請輸入每條邊對應的兩個頂點的序號:\n";

for (k=0;k<G->numEdge;k++){
    cout<<"v<i,j>:";
    cin>>i>>j; /*輸入e 條邊,建立鄰接矩陣*/
        G->edges[i][j]=1;
            }
}

void displaygraph(MGragh G){
int i,j;

for(i=0;i<G->numVertex;i++){
    for(j=0;j<G->numVertex;j++){
        cout<<G->edges[i][j]<<" ";}
    cout<<endl;
}
}

Edge FirstEdge(MGragh G,int oneVertex){
    Edge myEdge;
    myEdge.from=oneVertex;
    for(int i=0;i<G->numVertex;i++){
        if(G->edges[oneVertex][i]!=0){
            myEdge.to=i;
            myEdge.weight=G->edges[oneVertex][i];
            break;
        }
    }
    return myEdge;
}

Edge NextEdge(MGragh G,Edge preEdge){
    Edge myEdge;
    myEdge.from =preEdge.from ;
    if(preEdge.to <G->numVertex){
        for(int i=preEdge.to+1;i<G->numVertex;i++){
            if(G->edges[preEdge.from][i]!=0){
                myEdge.to =i;
                myEdge.weight =G->edges[preEdge.from ][i];
                break;
            }
        }
    }
    return myEdge;
}

bool isEdge(MGragh G, Edge myEdge){
    int test=0;
    for(int i=0;i<G->numVertex;i++){
        if(myEdge.to>=0&&G->edges[myEdge.from][myEdge.to]==1)return true;
    }
    return false;
}

//深度優先周遊    
void DFS(MGragh G, int v){
    mark[v]=TRUE;
    cout<<G->vexs[v];
    for(Edge e=FirstEdge(G,v);isEdge(G,e);e=NextEdge(G,e)){
        if(mark[e.to]==FALSE) DFS(G,e.to);
    }
}

void DFSM(MGragh G,int v){
    for(int i=0;i<G->numVertex;i++){
        mark[i]=FALSE;
    }
    DFS(G,0);
}

//廣度優先周遊
void BFS(MGragh G, int v){
    for(int i=0;i<G->numVertex;i++){
        mark[i]=FALSE;
    }
    using std::queue;
    queue<int>Q;
    cout<<G->vexs[v];
    mark[v]=TRUE;
    Q.push(v);
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        for(Edge e=FirstEdge(G,u);isEdge(G,e);e=NextEdge(G,e))
            if(mark[e.to]==FALSE){
                cout<<G->vexs[e.to];
                mark[e.to]=TRUE;
                Q.push(e.to);
            }
    }
}

int main(){
    Mgragh *Graph = (Mgragh *)malloc(sizeof(Mgragh));
    CreateMGraph(Graph);
    displaygraph(Graph);
    cout<<endl;
    BFS(Graph,0);
    cout<<endl;
    DFSM(Graph,0);
    system("pause");
    return 0;
}

鄰接表

4430424-8b0a87964034a1f9.png
鄰接表
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<queue> 
using namespace std;
#define MAX_VERTEXT_NUM 20
typedef enum{FALSE,TRUE} Boolean;
Boolean mark[MAX_VERTEXT_NUM];

typedef struct edge{
    int from,to,weight;
}Edge,*Edged;

typedef struct ArcNode{
    int adjvex;
    struct ArcNode *nextArc;
    int weight;
}ArcNode;

typedef struct VNode{
    char data;
    ArcNode *firstArc;
}VNode, AdjList[MAX_VERTEXT_NUM];

typedef struct Indegree{
    int indegree;
}Indegree,indegree[MAX_VERTEXT_NUM];

typedef struct{
    AdjList verTices;
    int vexNum;
    int arcNum;
    int kind;
    indegree Indegree;
}ALGraph;

typedef struct Dist{
    int index;
    int length;
    int pre;
}Dist,*Dijk;

edge FirstEdge(ALGraph *G,int oneVertex){
    Edge myEdge;
    myEdge.from=oneVertex;
    ArcNode *temp=G->verTices[oneVertex].firstArc;
    if(temp->nextArc!=NULL){
        myEdge.to=temp->nextArc->adjvex;
        myEdge.weight=temp->nextArc->weight;
    }
    return myEdge;
}

edge NextEdge(ALGraph *G,Edge preEdge){
    Edge myEdge;
    myEdge.from =preEdge.from;
    ArcNode *temp=G->verTices[preEdge.from].firstArc;
    while(temp->nextArc!=NULL&&temp->adjvex<=preEdge.to)
        temp=temp->nextArc;
    if(temp->nextArc!=NULL){
        myEdge.to=temp->nextArc->adjvex;
        myEdge.weight=temp->nextArc->weight;
    }
    return myEdge;
}

bool isEdge(ALGraph *G, Edge myEdge){
    int n=0;
    ArcNode *p;
    p=G->verTices[myEdge.from].firstArc;
    while(p){
        if(p->adjvex==myEdge.to){
            n=0;
        }else{
            n=1;
        }
        p=p->nextArc;
    }
    if(n==0){return true;}
    else{
        return false;
    }
}

void CreateGraph(ALGraph *G)
{
    int i,j,k,weight;
    ArcNode *arcNode;
    printf_s("請輸入頂點數和邊數:");
    cin>>G->vexNum;
    cin>>G->arcNum;
    //建立頂點表
    printf_s("建立頂點表\n");
    for (i = 0; i < G->vexNum; i++)
    {
        printf_s("請輸入第%d個頂點:", i);
        cin>>G->verTices[i].data;
        arcNode = (ArcNode *)malloc(sizeof(ArcNode));
        arcNode->adjvex=i;
        arcNode->nextArc=NULL;
        G->verTices[i].firstArc=arcNode;
        G->Indegree[i].indegree=0;
    }
    //建立邊表
    printf_s("建立邊表\n");
    for (k = 0; k < G->arcNum; k++)
    {
        printf_s("請輸入(vi-vj)的頂點對序號");
        cin>>i;
        cin>>j;
        arcNode = (ArcNode *)malloc(sizeof(ArcNode));
        arcNode->adjvex = j;
        arcNode->nextArc = G->verTices[i].firstArc->nextArc;//插入表頭
        G->verTices[i].firstArc ->nextArc= arcNode;
        G->Indegree[j].indegree++;
    }
}

//顯示圖的鄰接表
void DisplayGraph(ALGraph *G)
{
    int i;
    for (i = 0; i < G->vexNum; i++)
    {
            cout<<G->Indegree[i].indegree;
            ArcNode *P= G->verTices[i].firstArc;
            printf_s("%d->", i);
        while (P != NULL)
        {
            printf_s("%d->", P->adjvex);
            P = P->nextArc;
        }
        printf_s("\n");
    }
}

//深度優先周遊
void DFSM(ALGraph *G,int i){
    ArcNode *p;
    cout<<G->verTices[i].data;
    mark[i]=TRUE;
    p=G->verTices[i].firstArc;
    while(p){
        if(mark[p->adjvex]==FALSE)
            DFSM(G,p->adjvex);
        p=p->nextArc;       
    }
}

void DFS(ALGraph *G){
    for ( int i=0; i<G->vexNum;i++)
        mark[i]=FALSE;
    for( int i=0; i<G->vexNum;i++)
        if(!mark[i])
            DFSM(G,i);
}

//廣度優先周遊
void BFS(ALGraph *G,int x){
    ArcNode *p;
    int w;
    using std::queue;
    queue<int> Q;
    for ( int i=0; i<G->vexNum;i++) {mark[i]=FALSE;}
    cout<<G->verTices[x].data;
    mark[x]=TRUE;
    Q.push(x);
    while(!Q.empty()){
        int v=Q.front();
        Q.pop();
        p=G->verTices[v].firstArc;
        while(p){
            int w=p->adjvex;
            if(mark[w]==FALSE){
                mark[w]=TRUE;
                cout<<G->verTices[w].data;
                Q.push(w);}
            p=p->nextArc;
            }
        }
}

//拓撲排序
void TopsortbyQueue(ALGraph*G){
    for(int i=0; i< G->vexNum;i++)
        mark[i]=FALSE;
    using std::queue;
    queue<int> Q;
    cout<<"拓撲序列為:"<<endl;
    for(int i=0; i< G->vexNum;i++){
        if(G->Indegree[i].indegree==0)
            Q.push(i);}
        while(!Q.empty()){
            int v=Q.front();
            Q.pop();
            cout<<v;
            mark[v]=TRUE;
            for(Edge e=FirstEdge(G,v);isEdge(G,e);e=NextEdge(G,e)){
                G->Indegree[e.to].indegree--;
                if(G->Indegree[e.to].indegree ==0)
                    Q.push(e.to);
            }
        }
        for(int i=0;i< G->vexNum;i++)
            if(mark[i]==FALSE){
                cout<<endl;
                cout<<"還有頂點未訪問,此圖有環。"<<endl;
                break;
            }
}

int main(){
    int x;
    int num;
    string edge;

    ALGraph *Graph = (ALGraph *)malloc(sizeof(ALGraph));
    CreateGraph(Graph);
    DisplayGraph(Graph);
    DFS(Graph);
    BFS(Graph,0);

    TopsortbyQueue(Graph);
    system("pause");
}

相關文章