資料結構篇:圖的遍歷(一:深度優先遍歷)
阿新 • • 發佈:2018-11-26
深度優先遍歷,也稱作深度優先搜尋,縮寫為DFS
深度優先遍歷從某個頂點出發,訪問此頂點,然後從v的未被訪問的鄰接點觸發深度優先便利圖,直至所有和v有路徑想通的頂點都被訪問到。
這樣我們一定就訪問到所有結點了嗎,沒有,可能還有的分支我們沒有訪問到,所以需要回溯(一般情況下都設定一個數組,來記錄頂點是否訪問到,如果訪問到就不執行DFS演算法,如果未被訪問過就執行DFS演算法)
以這張圖為例
我們約定,在沒有碰到重複頂點的情況下,優先選擇右手邊
那麼按深度優先遍歷就是:A B C D E F G H(此時這條線路已經走到盡頭,可是還有一個I頂點沒有遍歷,所以回到G,發現G的鄰接點都遍歷過了,再回到F,發現F的鄰接點也都遍歷過了。。。直到D頂點,發現I這個頂點沒有遍歷,所以把I再遍歷,繼續回溯,最終回到起點A) I
落實到程式碼就是
//訪問標誌的陣列,為1表示訪問過,為0表示未被訪問
int visted[100];
//鄰接表的深度優先遍歷演算法 void AdjacencyList::DFS(GraphAdjList *G, int i) { EdgeNode *p; visted[i] = 1; cout << G->adjList[i].data << "--"; p = G->adjList[i].firstedge; while (p) { if (!visted[p->adjvex]) { //遞迴訪問 DFS(G, p->adjvex); } p = p->next; } }
//鄰接表的深度遍歷操作 void AdjacencyList::DFSTraverse(GraphAdjList *G) { //初始化所有頂點都沒有訪問過 cout<<"深度優先遍歷結果為:"<<endl; for (int i = 0; i < G->numVertexes; i++) { visted[i] = 0; } for (int i = 0; i < G->numVertexes; i++) { if (visted[i] == 0) { DFS(G, i); } } }
完整程式碼
//
// Created by 煙雨迷離半世殤 on 2018/11/21.
//
#include <iostream>
using namespace std;
//訪問標誌的陣列,為1表示訪問過,為0表示未被訪問
int visted[100];
//邊表結點
typedef struct EdgeNode {
//頂點對應的下標
int adjvex;
//指向下一個鄰接點
struct EdgeNode *next;
} edgeNode;
//頂點表結點
typedef struct VertexNode {
//頂點資料
char data;
//邊表頭指標
edgeNode *firstedge;
} VertexNode, AdjList[100];
//集合
typedef struct {
AdjList adjList;
//頂點數和邊數
int numVertexes, numEdges;
} GraphAdjList;
class AdjacencyList {
public:
void CreateALGraph(GraphAdjList *G);
void ShowALGraph(GraphAdjList *G);
void DFS(GraphAdjList *G, int i);
void DFSTraverse(GraphAdjList *G);
void Test();
};
void AdjacencyList::CreateALGraph(GraphAdjList *G) {
int i, j, k;
edgeNode *e;
cout << "輸入頂點數和邊數" << endl;
//輸入頂點數和邊數
cin >> G->numVertexes >> G->numEdges;
//讀入頂點資訊,建立頂點表
for (i = 0; i < G->numVertexes; i++)
{
//輸入頂點資訊
cin >> G->adjList[i].data;
//將邊表置為空表
G->adjList[i].firstedge = NULL;
}
//建立邊表(頭插法)
for (k = 0; k < G->numEdges; k++)
{
cout << "輸入邊(vi,vj)上的頂點序號" << endl;
cin >> i >> j;
e = new EdgeNode;
e->adjvex = j;
e->next = G->adjList[i].firstedge;
G->adjList[i].firstedge = e;
e = new EdgeNode;
e->adjvex = i;
e->next = G->adjList[j].firstedge;
G->adjList[j].firstedge = e;
}
}
void AdjacencyList::Test() {
cout << "ALL IS OK." << endl;
}
void AdjacencyList::ShowALGraph(GraphAdjList *G) {
for (int i = 0; i < G->numVertexes; i++)
{
cout << "頂點" << i << ": " << G->adjList[i].data << "--firstedge--";
edgeNode *p = new edgeNode;
p = G->adjList[i].firstedge;
while (p)
{
cout << p->adjvex << "--Next--";
p = p->next;
}
cout << "--NULL" << endl;
}
}
void AdjacencyList::DFS(GraphAdjList *G, int i) {
EdgeNode *p;
visted[i] = 1;
cout << G->adjList[i].data << "--";
p = G->adjList[i].firstedge;
while (p)
{
if (!visted[p->adjvex])
{
//遞迴訪問
DFS(G, p->adjvex);
}
p = p->next;
}
}
void AdjacencyList::DFSTraverse(GraphAdjList *G) {
//初始化所有頂點都沒有訪問過
cout<<"深度優先遍歷結果為:"<<endl;
for (int i = 0; i < G->numVertexes; i++)
{
visted[i] = 0;
}
for (int i = 0; i < G->numVertexes; i++)
{
if (visted[i] == 0)
{
DFS(G, i);
}
}
}
int main() {
AdjacencyList adjacencyList;
GraphAdjList *GA = new GraphAdjList;
adjacencyList.Test();
adjacencyList.CreateALGraph(GA);
adjacencyList.ShowALGraph(GA);
adjacencyList.DFSTraverse(GA);
return 0;
}
以這張圖為基準輸入
執行結果