日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法十——深度优先搜索和广度优先搜索

發布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法十——深度优先搜索和广度优先搜索 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章出處:極客時間《數據結構和算法之美》-作者:王爭。該系列文章是本人的學習筆記。

搜索算法

算法是作用于數據結構之上的。深度優先搜索、廣度優先搜索是作用于圖這種數據結構之上的。圖上的搜索算法可以理解為從一個頂點到另外一個頂點。

常用的搜索算法有:暴力的深度優先搜索、廣度優先搜索,還有A*、IDA*等啟發式搜索。

實際應用舉例

在社交網絡中有六度分隔理論,就是一個人最多通過六個人可以認識另外一個人。一個用戶的一度好友就是他的好友,二度好友是他好友的好友,以此類推。給你一個關系圖,你可以找到一個用戶的三度好友嗎?

廣度優先搜索(BFS)

BFS:先找離起始頂點最近的點,然后是次近,依次向外搜索。

下面的代碼是無向圖的BFS代碼。

/*** 無向圖*/ public class UnDirectedGraph {private int v;//頂點個數private LinkedList<Integer> adj[];//鄰接表public UnDirectedGraph(int v){this.v = v;this.adj = new LinkedList[v];for(int i=0;i<v;i++){this.adj[i] = new LinkedList<>();}}public void addEdge(int s,int t){this.adj[s].add(t);this.adj[t].add(s);}/*** 廣度優先搜索從s節點到t節點:打印從s到t的節點路徑* @param s* @param t*/public void bfs(int s, int t) {if(s==t){System.out.println(s);return;}Queue<Integer> queue = new LinkedList<>();queue.offer(s);boolean[] visited = new boolean[this.v];visited[s] = true;int[] pre = new int[v];Arrays.fill(pre,-1);while(!queue.isEmpty()){int size = queue.size();for(int i =0;i<size;i++){//每一層int w = queue.poll();for(int j =0;j<this.adj[w].size();j++){int q = this.adj[w].get(j);if(!visited[q]){pre[q] = w;if(q==t){printPath(pre,s,t);return;}visited[q]=true;queue.offer(q);}}}}}private void printPath(int[] pre,int s,int t) {if(s!=t && pre[t]!=-1){printPath(pre,s,pre[t]);}System.out.print(t+"\t");} }

這里三個重要的臨時變量queue、visited、pre。
queue:是一個隊列,存儲已經被訪問,但是鄰接點還沒有被訪問的節點。
visited:記錄已經訪問過的節點,防止重復訪問。
pre:記錄從哪個節點可以達到下標所表示的節點。pre[w]記錄從哪個節點達到w節點 。

時間復雜度分析:BFS中每個節點都會被訪問一次,入隊一次,每條邊都會被訪問一次,時間復雜度O(V+E)。V表示頂點個數,E表示邊的個數。

空間復雜度分析:臨時變量queue、visited、pre的個數都不會超過頂點個數。所以上O(V)。

上面的代碼可以抽象出BFS代碼的框架。

深度優先搜索(DFS)

DFS:DFS是從起始頂點開始,按照一條路徑一直走到終點t或者不能再走下去。然后返回到上一個可選擇的狀態,選擇另外一條路徑,繼續走。DFS是一種非常有名的算法思想:回溯。

下圖中實現代表搜索路徑,虛線代表回退。

private boolean found = false;public void dfs(int s, int t) {boolean[] visited = new boolean[this.v];int[] pre = new int[v];Arrays.fill(pre,-1);dfs(s,t,visited,pre);printPath(pre,s,t);}private void dfs(int w, int t, boolean[] visited, int[] pre) {if(w==t){found = true;return;}visited[w] = true;if(!found){for(int j =0;j<this.adj[w].size() && !found;j++){int q = this.adj[w].get(j);if(!visited[q]) {pre[q] = w;visited[q]=true;dfs(q,t,visited,pre);}}}}

時間復雜度分析:從圖中看每條邊最多被訪問2次,一次搜索,一次回退。時間復雜度O(E)。

空間復雜度分析:消耗內存主要是 visited、prev 數組和遞歸調用棧。visited、prev 數組和頂點個數相同。遞歸調用不會超過頂點的個數。所以空間復雜度O(V)。

適用范圍

DFS和BFS搜索的空間復雜度都是O(V),當頂點個數很大的時候,就不適合這兩種算法。

三度好友

上面提到的查找一個人的三度好友適合用BFS。一層一層向外搜索。找到第三層。

總結

以上是生活随笔為你收集整理的算法十——深度优先搜索和广度优先搜索的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。