寫在前面:科班出身,應屆考研黨,願21考研成功上岸,沖沖衝!
目錄
一、樹的深度優先遍歷
void PreOrder(TreeNode *R){
if(R != NULL){
visit(R);
while(R還有下一個子樹T)
PreOrder(T);
}
}
樹的深度優先遍歷(先根、後根):
從根節點出發,能往更深處走就走。每當訪問一個結點的時候,要檢查是否還有與當前結點相鄰的且沒有被訪問過的結點,如果有的話就往下一層鑽。
注:新找到的相鄰結點一定是沒有訪問過的
下圖先根遍歷序列:12563478
二、圖的深度優先遍歷
bool visited[MAX_VERTEX_NUM]; //訪問標記數組
void DFS(Graph G,int v){ //從頂點v出發,深度優先遍歷圖G
visit(v); //訪問頂點v
visited(v) = TRUE; //設已訪問標記
for(w = FirstNeighbor(G,v); w >= 0; w = NextNeighbor(G,v,w))
if(!visited[w]) //w爲u的尚未訪問的鄰接頂點
DFS(G,w);
}
三、算法存在的問題
如果是非連通圖圖,則無法遍歷完所有結點
四、DFS算法(Final版)
bool visited[MAX_VERTEX_NUM]; //訪問標記數組
void DFSTraverse(Graph G){
for(v = 0; v < G.vexnum;++v)
visited[v] = FALSE;
for(v = 0; v < G.vexnum;++v)
if(!visited[v])
DFS(G,v);
}
void DFS(Graph G,int v){ //從頂點v出發,深度優先遍歷圖G
visit(v); //訪問頂點v
visited(v) = TRUE; //設已訪問標記
for(w = FirstNeighbor(G,v); w >= 0; w = NextNeighbor(G,v,w))
if(!visited[w]) //w爲u的尚未訪問的鄰接頂點
DFS(G,w);
}
五、複雜度分析
空間複雜度
最壞情況:遞歸深度爲O(|V|)
最好情況:O(1)
時間複雜度
時間複雜度=訪問各結點所需時間+探索各條邊所需時間
鄰接矩陣存儲的圖:
訪問|V|個頂點需要O(|V|)的時間
查找每個頂點的鄰接點都需要O(|V|)的時間,而總共有|V|個頂點
時間複雜度:O(|V|^2)
鄰接表存儲的圖:
訪問|V|個頂點需要O(|V|)的時間
查找各個頂點的鄰接點共需要O(|E|)的時間
查找各個頂點的鄰接點共需要O(|E|)的時間
時間複雜度= O(|V|+|E|)
六、深度優先遍歷序列
從2出發的深度優先遍歷序列:21563478
從3出發的深度優先遍歷序列:34762158
從1出發的深度優先遍歷序列:12634785
注:
同一個圖的鄰接矩陣表示方式唯一,因此深度優先遍歷序列唯一
同一個圖的鄰接表表示訪問不唯一,因此深度優先遍歷序列不唯一
七、深度優先生成樹
同一個圖的鄰接矩陣表示方式唯一,因此深度優先遍歷序列唯一,深度優先生成樹也唯一
同一個圖的鄰接表表示訪問不唯一,因此深度優先遍歷序列不唯一,深度優先生成樹也不唯一
八、深度優先生成樹森林
九、圖的遍歷與圖的連通性
對無向圖進行BFS/DFS遍歷,調用BFS/DFS函數的次數=連通分量數
對於連通圖,只需調用1次BFS/DFS
對有向圖進行BFS/DFS遍歷,調用BFS/DFS函數的次數要具體問題具體分析
若起始頂點到其他各頂點都有路徑,則只需調用1次BFS/DFS函數
對強連通圖,從任一結點出發都只需調用1次BFS/DFS
十、總結