DepthFirstSearch BreadthFirstSearch
DFS & BFS
目录
- DFS BFS
- 概述
- 原理
- 实现
- Summary
概述
深度优先搜索和广度优先搜索是图论算法里的两种图的遍历方式,理解了两种搜索的原理之后,会发现算法和数据结构真的是不可分离的。
原理
深度优先搜索
在访问图中的其中一个顶点时:- 把它标记为已访问;
- 递归地访问它的所有没有被标记过的邻居节点。
递归方法说明我们可以利用栈的特点来说明深度优先搜索,举一个例子就行了:
栈: FILO,先进后出,后进先出
假设遍历从0开始,那么
- 访问0,并标记为已访问,0入栈 (0)
- 先找到第一个节点1,访问它,并标记为已访问,1入栈 (1, 0)
- 再从1开始,访问1的邻接点4,并标记为已访问,4入栈 (4, 1, 0)
- 节点4没有邻接点了,4出栈,回到节点1,访问邻接点5,5入栈,并标记为已访问 (5, 1, 0)
- 节点5没有邻接点了,5出栈,回到节点1,节点1也没有邻接点了,1出栈,回到节点0 (0)
- 访问0的第二个邻接点2,2入栈,以此类推 (2, 0)
得到的深度优先搜索顺序应该是:0,1,4,5,2,3,6
这是一个不断入栈和出栈的过程广度优先搜索
在访问图中的其中一个顶点时:- 把它标记位已访问
- 先把所有邻接点遍历完,再遍历邻接点的所有邻接点
因此,遍历邻接点完成后,还要回到第一个邻接点处,来遍历其邻接点,再遍历第二个邻接点的邻接点,以此类推。可以用队列来说明广度优先搜索。
队列:FIFO,先进先出,后进后出
还是上面那张图来举例。
假设遍历从0开始,那么- 访问0,并标记为已访问
- 先找到第一个节点1,1入队 (1)
- 再相继找到余下的节点2和3,2,3相继入队 (3, 2, 1)
- 0没有邻接点了,队头出队,得到节点1 (3, 2)
- 访问1,并标记为已访问,重复以上步骤。
得到的广度优先搜索顺序应该是:0,1,2,3,4,5,6
这是一个不断入队和出队的过程
实现
原理弄清楚了,实现起来就很简单了,按照步骤写出来即可。
import java.util.*;public class SearchTest { public static void main(String[] args) {Graph g = new Graph(7);g.addEdge(0, 1);g.addEdge(0, 2);g.addEdge(0, 3);g.addEdge(1, 4);g.addEdge(1, 5); g.addEdge(3, 6); // 按照节点关系的结构构造图Search s = new Search(g);System.out.println("dfs:");s.dfs(0); // 从0开始搜索s.clear();System.out.println();System.out.println("====================");System.out.println("bfs:");s.bfs(0); }
}class Search {private boolean[] marked;private int count;private Graph G;Queue<Integer> queue; // 用于bfspublic Search(Graph G) {marked = new boolean[G.V()];this.G = G; queue = new LinkedList<Integer>(); }/*** v是顶点*/public void dfs(int v) {marked[v] = true; count++;System.out.print(v + " "); // 以上三行,访问顶点并标记为已访问for(int w: G.adj(v)) {if(!marked[w]) dfs(w); // 若邻接点w没有被访问,以w为顶点,dfs}}/*** v为顶点*/public void bfs(int v) {marked[v] = true; count++;System.out.print(v + " "); // 以上三行,访问顶点并标记为已访问 for(int w: G.adj(v)) {if(!marked[w]) {queue.offer(w); // 如果邻接点w没有被访问,放入队列} }Integer head = queue.poll(); // v已经没有邻接点了,弹出队头if(head != null) { // 如果队头存在bfs(head); // 以队头为顶点,bfs} }public int count() { return count;}public void clear() {count = 0;for(int i = 0; i < marked.length; ++i) {marked[i] = false;}}
}@SuppressWarnings("unchecked")
class Graph {private final int V; // 顶点数目private int E; // 边的数目private List<Integer>[] adj;public Graph(int V) {this.V = V;adj = new ArrayList[V];for(int v = 0; v < V; v++){adj[v] = new ArrayList<>();}}// 把顶点v和w连成一条边public void addEdge(int v, int w) {adj[v].add(w);adj[w].add(v);E++;}public int E() {return E;}public int V() {return V;}// 返回顶点v的所有邻接点的集合public List<Integer> adj(int v) {return adj[v];}
}//output
dfs:
0 1 4 5 2 3 6
====================
bfs:
0 1 2 3 4 5 6
Summary
DFS和BFS是两种图的遍历算法,很简洁,同时也是两种数据结构Stack和Queue的良好应用。
DataStructure & Algorithms –> Twins
DepthFirstSearch BreadthFirstSearch相关推荐
- 算法C++ DepthFirstSearch BreadthFirstSearch代码模式示范实现(第四章)
文章目录 造轮子博客链接 DFS代码实现(递归模板示范) 代码实现(BFS模板示范) 造轮子博客链接 算法第四版C++算法实现全集 DFS可在STL中补充功能 下面的代码模式是结合的邻接表 C++ 邻 ...
- C#LeetCode刷题之#695-岛屿的最大面积( Max Area of Island)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3736 访问. 给定一个包含了一些 0 和 1的非空二维数组 gr ...
- 图的深度优先搜索和广度优先搜索(邻接表) - Java实现
文章目录 前言 1.什么是图? 2.图如何表示? 3.如何创建一个邻接表 一.深度优先搜索(Depth First Search) 二.广度优先搜索(Breadth First Search) 三.寻 ...
- 树的Breadth-First-Search和Depth-First-Search的java实现
假设待搜索的多叉树结构如下: 1 / | \ 3 5 7 / | \ | / \ 9 2 4 6 8 10 对应的代码如下: ...
- 广度优先搜索(BreadthFirstSearch) 迪克斯特拉算法 (Dijkstra's algorithm)
BFS可回答两类问题: 1.从节点A出发,有前往节点B的路径吗? 2.从节点A出发,前往节点B的哪条路径经过的节点最少? BFS中会用到"队列"的概念.队列是一种先进先出(FIFO ...
- Go:DepthFirstSearch深度优先搜索算法(附完整源码)
Go:DepthFirstSearch深度优先搜索算法 package graphfunc GetIdx(target int, nodes []int) int {for i := 0; i < ...
- 深度优先搜索算法(Depth-First-Search,DFS)与广度优先搜索算法(Breadth-First Search,BFS)理解
最近学习到了这两种经典的算法,谈一下自己的理解 深度优先搜索算法(Depth-First-Search,DFS) 这个算法会尽可能深的搜索树的分支.当节点v的所在边都己被探寻过,搜索将回溯到发现节点v ...
- 宽度优先搜索算法-BreadthFirstSearch(BFS)
package com.xch3.wide;import java.util.ArrayList; import java.util.List; import java.util.Scanner;pu ...
- 深度优先搜索_0基础学算法 搜索篇第一讲 深度优先搜索
0基础学算法 搜索篇第一讲 深度优先搜索 相信绝大多数人对于深度优先搜索和广度优先搜索是不会特别陌生的,如果我这样说似乎你没听说过,那如果我说dfs和bfs呢?先不说是否学习过它们,至少它们的大名应该 ...
最新文章
- 在SQL Server 2000 和SQL Server 2005中导出表结构
- 程序员能成为设计师吗
- Linux基础命令---shutdown
- 【整理】内向交货(Inbound Delivery)
- php 正则表达式 环视,php正则表达式环视详解
- linux中fg jobs ctrl-z bg操作和kill-15、kill-9杀死进程
- windows nssm将应用程序做成服务的实例
- Spring MVC常用注解,你会几个?
- Android Studio 导入新工程项目
- 小例子学习C#扩展方法
- hbase 页面访问_HBase在滴滴出行的应用场景和最佳实践
- 关闭Windows 2008下面应用程序出错后的提示
- 五、Oracle学习笔记:DQL数据查询语句
- 什么是模型?什么是数学模型?
- rv1126 固件编译规则
- 基于AD9361的ASK调制与解调
- 如何在直播、会议、视频中使用虚拟形象
- php以大写字母分割,js按大写字母拆分字符串
- 彻底解决idea maven依赖报红报错问题
- NOI 1818:红与黑(C++)