文章出处:极客时间《数据结构和算法之美》-作者:王争。该系列文章是本人的学习笔记。

搜索算法

算法是作用于数据结构之上的。深度优先搜索、广度优先搜索是作用于图这种数据结构之上的。图上的搜索算法可以理解为从一个顶点到另外一个顶点。

常用的搜索算法有:暴力的深度优先搜索、广度优先搜索,还有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。一层一层向外搜索。找到第三层。

算法十——深度优先搜索和广度优先搜索相关推荐

  1. Java实现算法导论中图的广度优先搜索(BFS)和深度优先搜索(DFS)

    对算法导论中图的广度优先搜索(BFS)和深度优先搜索(DFS)用Java实现其中的伪代码算法,案例也采用算法导论中的图. import java.util.ArrayList; import java ...

  2. 数据结构学习笔记——图的遍历算法(深度优先搜索和广度优先搜索)

    目录 一.图的遍历概念 二.深度优先搜索(DFS) (一)DFS算法步骤 1.邻接表DFS算法步骤 2.邻接矩阵DFS算法步骤 (二)深度优先生成树.森林 (三)DFS的空间复杂度和时间复杂度 三.广 ...

  3. 八数码深度优先搜索_深度优先搜索和广度优先搜索

    深度优先搜索和广度优先搜索 关于搜索&遍历 对于搜索来说,我们绝大多数情况下处理的都是叫 "所谓的暴力搜索" ,或者是说比较简单朴素的搜索,也就是说你在搜索的时候没有任何所 ...

  4. 深度优先搜索和广度优先搜索

    深度优先搜索和广度优先搜索 ​ 在人工智能的运筹学的领域中求解与图相关的应用中,这两个算法被证明是非常有用的,而且,如需高效地研究图的基本性质,例如图的连通性以及图是否存在环,这些算法也是必不可少的. ...

  5. 学会二叉树不知道干啥?二叉树的深度优先搜索和广度优先搜索,我要打十个乃至二十个(打开你的LeetCode撸起来)学练并举

    目录 一. 图解二叉树的深度优先搜索 二. 二叉树的广度优先搜索  (层序遍历) 三. 打开LeetCode 撸起来 至此, 咱多少被刚刚的后序非递归搞得可能有点小晕晕的, 没事,层序简单呀....  ...

  6. 深度优先遍历和广度优先遍历_图与深度优先搜索和广度优先搜索

    什么是图? 图是一种复杂的非线性表结构.由若干给定的点一级任意两点间的连线所构成.图通常用来描述事物之间的特定关系, 代表的就是事物, 线就是事物之间所具有的关系.例如社交网络就是一种典型的图关系, ...

  7. 迷宫问题:深度优先搜索和广度优先搜索

    迷宫问题:深度优先搜索和广度优先搜索 1.深度优先搜索可以使用栈实现,栈顶元素为当前节点 2.当前节点搜索下一节点,判断节点是否走得通,如果走得通任意方向走一步,走不通一直弹出栈内元素,直到走得通 3 ...

  8. 深度优先搜索与广度优先搜索区别和案例

    今天周末,心血来潮打开LeetCode做一道题: https://leetcode-cn.com/problems/number-of-enclaves/ 看到题,我的第一想法是: 从边缘的陆地开始, ...

  9. 数据结构与算法(python):广度优先搜索(Breadth First Search,BFS)和深度优先算法(Depth First Search,DFS)

    参考自 MOOC数据结构与算法Python版 目录 一.广度优先搜索 1.1 BFS算法过程 1.2 广度优先搜索算法分析 二.深度优先搜索 2.1 骑士周游 2.1.1 问题定义 2.1.2 构建骑 ...

最新文章

  1. .Net Core快速创建Windows服务
  2. from .pycaffe import Net, SGDSolver, NesterovSolver, AdaGradSolver, RMSPropSolver, AdaDeltaSolver,
  3. 血泪史:阿里云+ubuntu+vnc+xfce4
  4. KVO - 观察自定义属性值
  5. 【Android】选项卡使用
  6. cad加载dll_关于CAD三维建模的35个问题
  7. 6/6 音视频技术大咖在线直播,教你开发者硬核个人成长指南
  8. EEG有效连接工具包SIFT的介绍与安装
  9. ubuntu几款好用的代码编辑器
  10. php新浪微博 登录接口文档,php新浪微博登录接口用法实例,php新浪_PHP教程
  11. Win10麦克风显示这个设备正常但是没声音怎么解决
  12. WPF无边框窗体拖动
  13. vue如何整个页面添加loading
  14. 广电时评 | 中央主流媒体盛赞爱奇艺短剧新气象
  15. 2022茶艺师(中级)复训题库及模拟考试
  16. osg学习(三十一)osg、Qt的image
  17. TIDB简介及基础架构
  18. 套汇问题 Floyd
  19. Fiido Riding苹果app的技术支持网址
  20. 传统网络游戏(偏重MMORPG)的模块划分

热门文章

  1. JAVA 成员访问权限修饰符
  2. 程序员的生存发展和出路
  3. jquery通过attr取html里自定义属性原来这么方便啊
  4. javascript立即调用的函数表达式
  5. WINCE6 同时支持简繁体
  6. URLEncoder 、URLDecoder 对中文转码解码使用
  7. postgresql查询mysql库_postgresql 查看数据库,表,索引,表空间以及大小
  8. java——获取视频某一帧的图片
  9. 2017年计算机组成原理1254,2018年7月试卷号1254计算机组成原理A.pdf
  10. (JAVA)Random类