DFS-BFS(深搜广搜)原理及C++代码实现
深搜和广搜是图很多算法的基础,很多图的算法都是从这两个算法中启发而来。
深搜简单地说就是直接一搜到底,然后再回溯,再一搜到底,一直如此循环到没有新的结点。
广搜简单地说就是一层一层的搜,像水的波纹一样往外面扩散,扩散到最外层搜索也就完成了。
prim最小生成树、Dijkstra单源最短路径算法都使用了类似广度优先搜索的思想。
拓扑排序就可以用深搜来实现,分解强连通分量也可以用深搜来实现(转置图加两次深搜)
我们实现广搜时需要用队列来辅助我们进行。实现深搜时使用栈来辅助我们进行,所以显而易见的用递归实现深搜也比较合适,因为递归本身就是栈存储。
下面给出的广搜是无向图中,给定源结点的方法。
给出的深搜是有向图中,未给出源结点的方法,且是非递归实现(递归实现相对比较简单)。
代码如下:(仅供参考)
1 template<typename T> 2 class Graph { 3 private : 4 struct Vertex { 5 forward_list<T> vertex; 6 bool color; 7 }; 8 typedef unordered_map<T, Vertex> adjList; 9 adjList Adj; 10 public : 11 void insertEdge(T x, T y) {Adj[x].vertex.push_front(y);} 12 void deleteEdge(T x, T y) {Adj[x].vertex.remove(y);} 13 void BFS(T s); 14 void DFS(); 15 }; 16 17 template<typename T> 18 void Graph<T>::BFS(T s) { 19 vector<T> que; 20 for (auto i : Adj) 21 i.second.color = false; 22 Adj[s].color = true; 23 cout << s << ends; 24 que.insert(que.begin(), s); 25 while (!que.empty()) { 26 T u = que.back(); 27 que.pop_back(); 28 for (auto i : Adj[u].vertex) 29 if (Adj[i].color == false) { 30 Adj[i].color = true; 31 cout << i << ends; 32 que.insert(que.begin(), i); 33 } 34 } 35 } 36 37 template<typename T> 38 void Graph<T>::DFS() { 39 vector<T> stk; 40 for (auto i : Adj) 41 i.second.color = false; 42 for (auto u : Adj) 43 if (u.second.color == false) { 44 T v = u.first; 45 while (1) { 46 if (Adj[v].color == false) { 47 cout << v << ends; 48 Adj[v].color = true; 49 } 50 auto p = Adj[v].vertex.begin(); 51 for ( ; p != Adj[v].vertex.end(); ++p) 52 if (Adj[*p].color == false) { 53 stk.push_back(v); 54 v = *p; 55 break; 56 } 57 if (p == Adj[v].vertex.end() && !stk.empty()) { 58 v = stk.back(); 59 stk.pop_back(); 60 } 61 else if (stk.empty()) break; 62 } 63 } 64 }