圖的遍歷---廣度優先遍歷和深度優先遍歷


    圖的遍歷:從圖的任意一個頂點出發,按照某一種次序,對圖中的所有頂點訪問一次並且只能訪問一次。遍歷經常

用兩種方法:廣度優先遍歷和深度優先遍歷。

    廣度優先遍歷:類似於樹的按層次遍歷的過程。假設從圖中某頂點v出發,在訪問了v之后依次訪問v的各個未曾訪問

過的鄰接點,然后分別從這些鄰接點出發依次訪問它們的鄰接點,並使“先被訪問的頂點的鄰接點”先於“后被訪問的

頂點的鄰接點”被訪問,直至圖中所有已被訪問的頂點的鄰接點都被訪問到。若此時圖中尚有頂點未被訪問,則另選圖

中的一個未曾被訪問的頂點作為起始點,重復上述過程,直至圖中所有頂點都被訪問到為止。

    深度優先遍歷:類似於樹的先根遍歷,是樹的先根遍歷的推廣。假設初始狀態是圖中所有頂點未曾被訪問,則深度

優先遍歷可從圖中某個頂點v出發,訪問此頂點,然后依次從v的未被訪問的鄰接點出發深度優先遍歷圖,直至圖中所有

和v有路徑想通的頂點都被訪問到;若此時圖中尚有頂點未被訪問,則另選圖中一個未曾被訪問的頂點作為起始點,重復

上述過程,直至圖中所有頂點都被訪問到為止。

    下面用代碼來實現兩種遍歷方法:

#include <iostream>
#include <queue> using namespace std; #define SIZE 10 struct Edge { Edge(int v):destvalue(v),link(NULL){} int destvalue; Edge *link; }; struct Vertex { Vertex():list(NULL){} char data; Edge *list; }; class GraphLink { public: GraphLink() { MaxVertex = SIZE; NumVertex = NumEdge = 0; VertexTable = new Vertex[MaxVertex]; } void InsertVertex(char v) { if(NumVertex >= MaxVertex) return; VertexTable[NumVertex++].data = v; } int GetVertexI(char v) { for(int i = 0;i<NumVertex;i++) { if(VertexTable[i].data == v) return i; } return -1; } void InsertEdge(char v1,char v2) { int p1 = GetVertexI(v1); int p2 = GetVertexI(v2); if(p1 == -1 || p2 == -1) return; Edge *ed = new Edge(p2); ed->link = VertexTable[p1].list; VertexTable[p1].list = ed; ed = new Edge(p1); ed->link = VertexTable[p2].list; VertexTable[p2].list = ed; NumEdge++; } void Show() { Edge *ed = NULL; for(int i = 0;i<NumVertex;i++) { cout<<i<<":"<<VertexTable[i].data<<"->"; ed = VertexTable[i].list; while(ed) { cout<<ed->destvalue<<"->"; ed = ed->link; } cout<<"nul"<<endl; } } void BFS(char value) { queue<int> q; int v = GetVertexI(value); bool *visited = new bool[NumVertex]; Edge *ed = NULL; int w; for(int i = 0;i<NumVertex;i++) visited[i] = false; if(v == -1) return; cout<<value<<" "; visited[v] = true; q.push(v); while(!q.empty()) { v = q.front(); q.pop(); ed = VertexTable[v].list; while(ed) { w = ed->destvalue; if(!visited[w]) { cout<<VertexTable[w].data<<" "; q.push(w); visited[w] = true; } ed = ed->link; } } } void DFS(char v) { bool *visited = new bool[NumVertex]; for(int i = 0;i<NumVertex;i++) visited[i] = false; DFS(GetVertexI(v),visited); delete [] visited; visited = NULL; } char GetVertex(int v) { return VertexTable[v].data; } void DFS(int v,bool *visited) { cout<<GetVertex(v)<<" "; visited[v] = true; int w = GetFirstNeighbor(v); while(w != -1) { if(!visited[w]) { DFS(w,visited); } w = GetNextNeighbor(v,w); } } int GetFirstNeighbor(int v) //v的第一個鄰接頂點 { if(v == -1) return -1; Edge *p = VertexTable[v].list; if(p) return p->destvalue; return -1; } int GetNextNeighbor(int v,int w) //v的鄰接頂點w的下一個鄰接頂點 { if(v == -1 || w== -1) return -1; Edge *p = VertexTable[v].list; while(p && p->destvalue != w) p = p->link; if(p && p->link) return p->link->destvalue; return -1; } private: int MaxVertex; int NumVertex; int NumEdge; Vertex *VertexTable; };

    在代碼的實現過程中借助了STL中的隊列,在上面的代碼中使用了鄰接表的結構進行存儲,先定義了邊的結構

了頂點在數組中的下標的值,還有一個指向下一個鄰接頂點的鏈表指針,然后定義了頂點的結構包含了頂點的數據和由

邊組成的一個鏈表。之后定義了圖的類,包含的數據有最大的頂點的個數、當前頂點的個數、當前邊的個數、頂點類型

的數組,實現的方法有(1)構造函數:對定義的數據進行初始化。(2)插入頂點函數。(3)得到頂點位置信息函數。

(4)插入邊的函數。(5)顯示構造的圖的信息的函數。(6)廣度優先遍歷函數。(7)深度優先遍歷函數。(8)得

到頂點數據的函數。(9)得到頂點v的第一個鄰接頂點的函數。(10)得到頂點v的鄰接頂點的下一個鄰接頂點的函數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM