1. 程式人生 > >圖的遍歷之DSF深度優先演算法6.2.1(網路整理)

圖的遍歷之DSF深度優先演算法6.2.1(網路整理)

圖的遍歷之深度優先演算法虛擬碼描述(和樹的前序遍歷相似,實際上樹可以看成特殊的圖:N個頂點有N-1條邊,不曾在迴路!即樹是圖連通中最少邊的情況)

圖片來自網路

如上圖:

深度優先遍歷:

先選取一個頂點訪問它,然後深度優先遍歷它的每個未訪問的鄰接點

#include<stdlib.h>
#include<stdbool.h>
#include<stdio.h>
#define MaxVertexNum 100    /* 最大頂點數設為100 */  
typedef int Vertex;         /* 用頂點下標表示頂點,為整型 */  
typedef int WeightType;        /* 邊的權值設為整型 */  
typedef char DataType;        /* 頂點儲存的資料型別設為字元型 */  
  
bool Visited[MaxVertexNum];


/* 邊的定義 */  
typedef struct ENode *PtrToENode;  
struct ENode{  
    Vertex V1, V2;      /* 有向邊<V1, V2> */  
    WeightType Weight;  /* 權重 */  
};  
typedef PtrToENode Edge;  
   
/* 鄰接點的定義 */  
typedef struct AdjVNode *PtrToAdjVNode;   
struct AdjVNode{  
    Vertex AdjV;        /* 鄰接點下標 */  
    WeightType Weight;  /* 邊權重 */  
    PtrToAdjVNode Next;    /* 指向下一個鄰接點的指標 */  
};  
   
/* 頂點表頭結點的定義 */  
typedef struct Vnode{  
    PtrToAdjVNode FirstEdge;/* 邊表頭指標 */  
    DataType Data;            /* 存頂點的資料 */  
    /* 注意:很多情況下,頂點無資料,此時Data可以不用出現 */  
} AdjList[MaxVertexNum];    /* AdjList是鄰接表型別 */  
   
/* 圖結點的定義 */  
typedef struct GNode *PtrToGNode;  
struct GNode{    
    int Nv;     /* 頂點數 */  
    int Ne;     /* 邊數   */  
    AdjList G;  /* 鄰接表 */  
};  
typedef PtrToGNode LGraph; /* 以鄰接表方式儲存的圖型別 */  

LGraph CreateGraph( int VertexNum )  
{ Vertex V;
/* 初始化一個有VertexNum個頂點但沒有邊的圖 */  
LGraph Graph=(LGraph)malloc(sizeof(struct GNode));
Graph->Nv=VertexNum;
Graph->Ne=0;
 /* 初始化鄰接表頭指標 */  
    /* 注意:這裡預設頂點編號從0開始,到(Graph->Nv - 1) */  
       for (V=0; V<Graph->Nv; V++)  
        Graph->G[V].FirstEdge = NULL;  
               
    return Graph;   
} 

void InsertEdge( LGraph Graph, Edge E )  {

PtrToAdjVNode NewNode;  
       
    /* 插入邊 <V1, V2> */  
    /* 為V2建立新的鄰接點 */  
    NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));  
    NewNode->AdjV = E->V2;  
    NewNode->Weight = E->Weight;  
    /* 將V2插入V1的表頭 */  
    NewNode->Next = Graph->G[E->V1].FirstEdge;  
    Graph->G[E->V1].FirstEdge = NewNode;  
           
    /* 若是無向圖,還要插入邊 <V2, V1> */  
    /* 為V1建立新的鄰接點 */  
    NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));  
    NewNode->AdjV = E->V1;  
    NewNode->Weight = E->Weight;  
    /* 將V1插入V2的表頭 */  
    NewNode->Next = Graph->G[E->V2].FirstEdge;  
    Graph->G[E->V2].FirstEdge = NewNode;  

}


    LGraph BuildGraph()  
    {  
        LGraph Graph;  
        Edge E;  
        Vertex V;  
        int Nv, i;  
           
        scanf("%d", &Nv);   /* 讀入頂點個數 */  
        Graph = CreateGraph(Nv); /* 初始化有Nv個頂點但沒有邊的圖 */   
           
        scanf("%d", &(Graph->Ne));   /* 讀入邊數 */  
        if ( Graph->Ne != 0 ) { /* 如果有邊 */   
            E = (Edge)malloc( sizeof(struct ENode) ); /* 建立邊結點 */   
            /* 讀入邊,格式為"起點 終點 權重",插入鄰接矩陣 */  
            for (i=0; i<Graph->Ne; i++) {  
                scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);   
                /* 注意:如果權重不是整型,Weight的讀入格式要改 */  
                InsertEdge( Graph, E );  
            }  
          free(E);
        }   
       
        /* 如果頂點有資料的話,讀入資料 */  
        for (V=0; V<Graph->Nv; V++)   
            scanf(" %c", &(Graph->G[V].Data));  
       
        return Graph;  
    }  

        /* 鄰接表儲存的圖 - DFS */
     
    void Visit( Vertex V )
    {
        printf("正在訪問頂點%d\n", V);
    }
     
    /* Visited[]為全域性變數,已經初始化為false */
    void DFS( LGraph Graph, Vertex V, void (*PVisit)(Vertex) )
    {   /* 以V為出發點對鄰接表儲存的圖Graph進行DFS搜尋 */
        PtrToAdjVNode W;
         
        (*PVisit)( V ); /* 訪問第V個頂點 */
        Visited[V] = true; /* 標記V已訪問 */
     
        for( W=Graph->G[V].FirstEdge; W; W=W->Next ) /* 對V的每個鄰接點W->AdjV */
            if ( !Visited[W->AdjV] )    /* 若W->AdjV未被訪問 */
                DFS( Graph, W->AdjV, PVisit );    /* 則遞迴訪問之 */
    }



    int main(){
     for(int i=0;i<MaxVertexNum;i++)
      Visited[i]=false;//初始化為false
      LGraph Graph=BuildGraph();
      DFS(Graph,0,Visit);

    return 0;
    }
#include<stdlib.h>
#include<stdbool.h>
#include<stdio.h>
#define MaxVertexNum 100    /* 最大頂點數設為100 */  
#define INFINITY 65535        /* ∞設為雙位元組無符號整數的最大值65535*/  
typedef int Vertex;         /* 用頂點下標表示頂點,為整型 */  
typedef int WeightType;        /* 邊的權值設為整型 */  
typedef char DataType;        /* 頂點儲存的資料型別設為字元型 */  
bool Visited[MaxVertexNum];  
/* 邊的定義 */  
typedef struct ENode *PtrToENode;  
struct ENode{  
    Vertex V1, V2;      /* 有向邊<V1, V2> */  
    WeightType Weight;  /* 權重 */  
};  
typedef PtrToENode Edge;  
          
/* 圖結點的定義 */  
typedef struct GNode *PtrToGNode;  
struct GNode{  
    int Nv;  /* 頂點數 */  
    int Ne;  /* 邊數   */  
    WeightType G[MaxVertexNum][MaxVertexNum]; /* 鄰接矩陣 */  
    DataType Data[MaxVertexNum];      /* 存頂點的資料 */  
    /* 注意:很多情況下,頂點無資料,此時Data[]可以不用出現 */  
};  
typedef PtrToGNode MGraph; /* 以鄰接矩陣儲存的圖型別 */  

MGraph CreateGraph( int VertexNum )  
{ /* 初始化一個有VertexNum個頂點但沒有邊的圖 */  
    Vertex V, W;  
    MGraph Graph;  
       
    Graph = (MGraph)malloc(sizeof(struct GNode)); /* 建立圖 */  
    Graph->Nv = VertexNum;  
    Graph->Ne = 0;  
    /* 初始化鄰接矩陣 */  
    /* 注意:這裡預設頂點編號從0開始,到(Graph->Nv - 1) */  
    for (V=0; V<Graph->Nv; V++)  
        for (W=0; W<Graph->Nv; W++) 
        if(V==W) 
        	Graph->G[V][W]=0;
        else  
            Graph->G[V][W] = INFINITY;  
               
    return Graph;   
}  

	void InsertEdge( MGraph Graph, Edge E )  {
	     /* 插入邊 <V1, V2> */  
	     Graph->G[E->V1][E->V2] = E->Weight;      
	     /* 若是無向圖,還要插入邊<V2, V1> */  
	     Graph->G[E->V2][E->V1] = E->Weight;  
	}
   

    MGraph BuildGraph()  
    {  
        MGraph Graph;  
        Edge E;  
        Vertex V;  
        int Nv, i;  
           
        scanf("%d", &Nv);   /* 讀入頂點個數 */  
        Graph = CreateGraph(Nv); /* 初始化有Nv個頂點但沒有邊的圖 */   
           
        scanf("%d", &(Graph->Ne));   /* 讀入邊數 */  
        if ( Graph->Ne != 0 ) { /* 如果有邊 */   
            E = (Edge)malloc(sizeof(struct ENode)); /* 建立邊結點 */   
            /* 讀入邊,格式為"起點 終點 權重",插入鄰接矩陣 */  
            for (i=0; i<Graph->Ne; i++) {  
                scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);   
                /* 注意:如果權重不是整型,Weight的讀入格式要改 */  
                InsertEdge( Graph, E );  
            }  
            free(E);
        }   
       
        /* 如果頂點有資料的話,讀入資料 */  
        for (V=0; V<Graph->Nv; V++)   
            scanf(" %c", &(Graph->Data[V]));  
       
        return Graph;  
    }  


    void Visit( Vertex V )
    {
        printf("正在訪問頂點%d\n", V);
    }



     /* Visited[]為全域性變數,已經初始化為false */
    void DFS( MGraph Graph, Vertex V, void (*PVisit)(Vertex) ){
    /* 以V為出發點對鄰接表儲存的圖Graph進行DFS搜尋 */
    	(*PVisit)( V ); /* 訪問第V個頂點 */
        Visited[V] = true; /* 標記V已訪問 */
        for(Vertex W=0;W<Graph->Nv;W++)              
        	if(!Visited[W]&&Graph->G[V][W]!=INFINITY&&V!=W) /* 對V的每個未被訪問de鄰接點*/
        	DFS(Graph,W,PVisit);

    }

    int main(){
     for(int i=0;i<MaxVertexNum;i++)
      Visited[i]=false;//初始化為false
      MGraph Graph=BuildGraph();
      DFS(Graph,0,Visit);

    return 0;
    }
用棧模擬