你必须会的DFS的递归实现与堆栈实现
生活随笔
收集整理的這篇文章主要介紹了
你必须会的DFS的递归实现与堆栈实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 一. 算法原理
- 1.堆棧式實現方法
- 2.遞歸式實現方法
- 二.具體實現
- 1.實例
- 2.結果
- 三.如何輸出所有的路徑?
一. 算法原理
相比于BFS利用隊列實現中心擴散式搜索
DFS就是利用堆棧的思想(先進后出),利用回溯算法,或者使用dfs遞歸,直觀上看是一條路走到黑,如果找到南墻,便回到上個路口,繼續一條路走到黑…如此往復,直到到達目標,所以稱之為深度優先搜索。
1.堆棧式實現方法
- 首先將根節點壓入堆棧中。
- 從堆棧中pop一個節點,并檢驗它是否為目標。
- 如果找到目標,則結束搜索并回傳結果。
- 否則將它所有尚未檢驗過的直接子節點加入堆棧中。
- 若堆棧為空,表示整張圖都檢查過了——亦即圖中沒有所搜索的目標。結束搜索并回傳“找不到目標”。
- 重復步驟2。
偽代碼
stack.push(root) while(!stack.isEmpty())node = stack.pop()for each neighbor node的相鄰節點if neighbor未被訪問stack.push(neightbor)//記錄路徑stack.parent = node//其余操作...todo...2.遞歸式實現方法
- 給定根節點
- 遍歷根節點所有未被訪問的相鄰節點
- 如果找到目標,則結束搜索并傳回結果
- 否則將該相鄰節點設置為新的根節點,重復步驟2
- 若沒有未被訪問的相鄰節點,則結束本分支的搜索并返回
- 所有分支都遍歷完畢,結束搜索并回傳“找不到目標”。
偽代碼:
DFS()dfsVisit(root)dfsVisit(node)for each neighbor node的相鄰節點if neighbor沒有訪問過//記錄路徑neighbor.parent = root//其他操作todo..dfs(neighbor)二.具體實現
選用常見的遞歸實現
package com.example.DFS;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;public class DFS {// <1, [2, 3]>表示節點1的父節點是節點2,到源點距離為3private Map<Integer, int[]> disTo;/*** @param edges 一個節點到其他節點的距離* [[0, 1, 1], [1, 2, 2]] 表示點0到點1的距離為1,點1到點2的距離為2* @param n 所有節點個數 1<= n <= 1000* @param k 源節點 1< k <n*/public Map<Integer, int[]> DFS(int[][] edges, int n, int k){//通過edges數組生成有向圖//<0, <{1,2}, {2,3}>>表示節點0有1,2兩個相鄰節點,距離分別為2, 3Map<Integer, List<int[]>> graph = new HashMap<>();for(int[] edge:edges){if(!graph.containsKey(edge[0]))graph.put(edge[0], new ArrayList<int[]>());graph.get(edge[0]).add(new int[]{edge[1], edge[2]});}//初始化disTodisTo = new HashMap<>();for(int i=0; i<n; i++){if(i==k)disTo.put(i, new int[]{k, 0});else disTo.put(i, new int[]{-1, Integer.MAX_VALUE});}dfsVisit(graph, k);return disTo;}/*** dfs* @param graph* @param k*/private void dfsVisit(Map<Integer, List<int[]>> graph, int k){if(graph.containsKey(k))for(int[] edge:graph.get(k)){int[] temp = disTo.get(edge[0]);//保證該節點未被訪問if(temp[0] == -1 && temp[1] == Integer.MAX_VALUE) {//setParent 記錄路徑temp[0] = k;//setDisTo 記錄距離temp[1] = disTo.get(k)[1] + edge[1];//遞歸實現dfsVisit(graph, edge[0]);}}}/*** 輸出結果* @param disTo* @param end*/public void printPath(Map<Integer, int[]> disTo,int pathTo){int distance = disTo.get(pathTo)[1];List<Integer> path = new ArrayList<>();int temp = pathTo;path.add(temp);while (temp!=0 && temp!=-1){temp = disTo.get(temp)[0];path.add(temp);}System.out.print("從初始節點到節點"+end+"的距離為"+distance+"\n"+"路徑為:\n"+path.get(0));for(int i=1;i<path.size();i++){System.out.print("<--"+path.get(i));}} }1.實例
測試輸入
輸入:
| {{0, 1, 15},{0, 3, 5}, | 6 | 0 | 4 |
| {1, 5, 6}, {3, 5, 20}, | |||
| {1, 2, 15}, {3, 2, 30}, | |||
| {2, 4, 10}, {5, 4, 9}}; |
預計輸出:距離:30 路徑:0–>1–>5–>4
環境:windows10,java11
2.結果
試著輸出到節點5的路徑和距離
三.如何輸出所有的路徑?
在一個圖沒有環的情況下,或者先去環后,允許一個節點可以由多個不同的父節點向下遍歷到,這樣可以找到圖中真正的所有路徑
你可能還敢興趣的圖論算法(均附Java實現代碼):
-
算法實驗–主函數只有五行的Floyed的算法以及最短路徑輸出
-
你必須會的–Dijkstra算法–單源最短路徑問題
-
你了解歐拉回路嗎?
-
你必須會的啟發式搜索算法–A*算法
總結
以上是生活随笔為你收集整理的你必须会的DFS的递归实现与堆栈实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSS伪元素速查
- 下一篇: 算法分析之-渐进记号