[C++] C++ DFS 記錄層數兩種寫法dfs(int v) dfs(int v,int level)
阿新 • • 發佈:2019-02-14
DFS
完整原始碼
DFS.cpp
// DFS.cpp
#include <iostream>
using namespace std;
bool marked[10];
int G[10][10];
int V,E;
int count;
void dfs(int v) {
count++;
int level;
level = count;
for(int i = 0 ;i < level ;i++)
cout << " ";
cout << "DFS " << v << " start : " << endl;
marked[v] = true;
for(int i = 0; i < V;i++)
if(!marked[i] && G[v][i]) dfs(i);
for(int i = 0 ;i < level ;i++)
cout << " ";
cout << "DFS " << v << " end. " << endl;
}
void readData() {
for(int i = 0; i < 10 ;i++)
for(int j = 0; j < 10; j++)
G[i][j] = -1;
cin >> V >> E;
for(int i = 0 ; i < E; i++) {
int v , w;
cin >> v >> w;
G[v][w] = 1;
}
count = 0;
}
int main()
{
readData();
dfs(0);
}
DFS2.cpp
// DFS2.cpp
#include <iostream>
using namespace std;
bool marked[10];
int G[10][10];
int V,E;
void dfs(int v, int level) {
level++;
for(int i = 0 ;i < level ;i++)
cout << " ";
cout << "DFS " << v << " start : " << endl;
marked[v] = true;
for(int i = 0; i < V;i++)
if(!marked[i] && G[v][i]) dfs(i, level);
for(int i = 0 ;i < level ;i++)
cout << " ";
cout << "DFS " << v << " end. " << endl;
}
void readData() {
for(int i = 0; i < 10;i++)
for(int j = 0; j < 10; j++)
G[i][j] = -1;
cin >> V >> E;
for(int i = 0 ; i < E; i++) {
int v , w;
cin >> v >> w;
G[v][w] = 1;
}
}
int main()
{
readData();
dfs(0, 0);
}
模擬資料
測試執行
4
3
0 1
1 2
2 3
DFS 0 start :
DFS 1 start :
DFS 2 start :
DFS 3 start :
DFS 3 end.
DFS 2 end.
DFS 1 end.
DFS 0 end.
--------------------------------
Process exited after 0.9161 seconds with return value 0
請按任意鍵繼續. . .
程式碼說明
有向圖的表示
int G[10][10];
- 整型二維陣列來表示有向圖,
G[v][w] == 1
表示 頂點v
到 頂點w
可達;
DFS過程
- DFS的本質過程,如果用虛擬碼來描述應該是 :
DFS(int v)
{
標記 v 為: 已訪問;
for 對於每個從v可達的頂點w :
如果 w 還沒被訪問過 ,那就 DFS(w);
}
- 基於本文使用的二維陣列來表示圖,所以程式碼實現層面可以簡單地用
for()
來遍歷整個二維陣列的一行,並且基於G[v][i]
的值來判斷是不是從v可達,具體程式碼如下:
dfs(int v) {
marked[v] = true;
for(int i = 0; i < V;i++)
if(!marked[i] && G[v][i]) dfs(i);
}
DFS.cpp 全域性變數count與本地變數level
int count;
void dfs(int v) {
count++;
int level;
level = count;
}
count
在本文中被宣告為一個全域性變數,這樣就不需要在DFS方法中增加引數,直接寫個count++
就可以在DFS
往深處搜尋的時候+1
,count
變數初始值是0
、從第一層的1
開始最終會變成4
;level
變數是一個區域性變數,是dfs
函式內部的變數,目的是記住每個dfs
當前的層數,以便在dfs
的開始start和結束end輸出相同數量的空格;
DFS2.cpp 與DFS.cpp記層數
dfs(int v)
void dfs(int v) {
count++;
int level;
level = count;
marked[v] = true;
for(int i = 0; i < V;i++)
if(!marked[i] && G[v][i]) dfs(i);
}
dfs(int v,int level)
void dfs(int v, int level) {
level++;
marked[v] = true;
for(int i = 0; i < V;i++)
if(!marked[i] && G[v][i]) dfs(i, level);
}
- 區別還是很明顯的,如果想要記錄下層數,這兩種寫法都是OK的。
聯絡思考
- 之前實現過 帶權有向圖的環檢測以及環輸出(點我,或者見引用[1]),當時用到的就是一種
DFS
的變形,演算法核心的就是在DFS
開頭以及 結束(對應本文兩次for{} cout
輸出)的位置,顯式地用一個onStak[]
布林陣列來記錄當前被訪問的頂點是不是正處在本次DFS
遞迴呼叫; - 無論是從模擬資料的圖片還是從測試執行部分的輸出來看,都可以很直觀地感受到
DFS
,這種遞迴的痕跡,0->1->2->3->3->2->1->0
,棧的FILO
非常明顯;