作者:Leo-Yang
原文都先发布在作者个人博客:http://www.leoyang.net/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

前言

图在算法世界中的重要地位是不言而喻的,曾经看到一篇Google的工程师写的一篇《Get that job at Google!》文章中说到面试官问的问题中几乎有一半的问题都可以用图的方法去解决。由此也可以看出图确实适用范围确实很广。

图的表示

闲话不多说,首先要介绍的就是图的表示,图最常用的两种表示方法是邻接表和邻接矩阵。顾名思义,这两种办法分别用表和矩阵的方式描述图中各顶点之间的联系

下图展示了两种表示上面这个图的方法

BFS

本文将着重介绍遍历图的两种最常用的方法,分别为广度优先遍历和深度优先遍历,后面会具体介绍为什么这么命名。首先来看广度优先遍历BFS(Breadth First Search),其主要思想是从起始点开始,将其邻近的所有顶点都加到一个队列(FIFO)中去,然后标记下这些顶点离起始顶点的距离为1.最后将起始顶点标记为已访问,今后就不会再访问。然后再从队列中取出最先进队的顶点A,也取出其周边邻近节点,加入队列末尾,将这些顶点的距离相对A再加1,最后离开这个顶点A。依次下去,直到队列为空为止。从上面描述的过程我们知道每个顶点被访问的次数最多一次(已访问的节点不会再访问),而对于连通图来说,每个顶点都会被访问。加上每个顶点的邻接链表都会被遍历,因此BFS的时间复杂度是Θ(V+E),其中V是顶点个数,E是边数,也就是所有邻接表中的元素个数。为了更好的说明这个过程,下图列出了对一个图的BFS的过程

private static void bfs(HashMap<Character, LinkedList<Character>> graph,HashMap<Character, Integer> dist,char start)
{
Queue<Character> q=new LinkedList<>();
q.add(start);//将s作为起始顶点加入队列
dist.put(start, 0);
int i=0;
while(!q.isEmpty())
{
char top=q.poll();//取出队首元素
i++;
System.out.println("The "+i+"th element:"+top+" Distance from s is:"+dist.get(top));
int d=dist.get(top)+1;//得出其周边还未被访问的节点的距离
for (Character c : graph.get(top)) {
if(!dist.containsKey(c))//如果dist中还没有该元素说明还没有被访问
{
dist.put(c, d);
q.add(c);
}
}
}
}

运行结果:

从运行结果我们也可以看到,w r作为距离为1的顶点先被访问,x t v其后,最后访问y u。上面的代码使用了一个小的trick,用dist这个hash表来记录每个顶点离s的距离,如果dist中没有这个元素则说明还未被访问,这时将距离写入dist中。BFS访问得到的每个节点与起始顶点的距离是起始顶点到达该顶点的最短距离。从感性认识上来说,BFS向外扩散的方式得到的距离就是最短距离。详细的证明过程请参考CLRS上的相应章节

DFS

DFS(Depth First Search)深度优先搜索是从起始顶点开始,递归访问其所有邻近节点,比如A节点是其第一个邻近节点,而B节点又是A的一个邻近节点,则DFS访问A节点后再访问B节点,如果B节点有未访问的邻近节点的话将继续访问其邻近节点,否则继续访问A的未访问邻近节点,当所有从A节点出去的路径都访问完之后,继续递归访问除A以外未被访问的邻近节点。因为是递归过程,所以我们用过程图看一下也许会更直观一些。

如下是DFS的代码及运行结果

private static void dfs(HashMap<Character , LinkedList<Character>> graph,HashMap<Character, Boolean> visited)
{
visit(graph, visited, 'u');//为了和图中的顺序一样,我认为控制了DFS先访问u节点
visit(graph,visited,'w');
}
private static void visit(HashMap<Character , LinkedList<Character>> graph,HashMap<Character, Boolean> visited,char start)
{
if(!visited.containsKey(start))
{
count++;
System.out.println("The time into element "+start+":"+count);//记录进入该节点的时间
visited.put(start, true);
for (char c : graph.get(start))
{
if(!visited.containsKey(c))
{
visit(graph,visited,c);//递归访问其邻近节点
}
}
count++;
System.out.println("The time out element "+start+":"+count);//记录离开该节点的时间
}
}

运行结果:

我们通过一个全局变量count记录了进入每个节点和离开每个节点的时间,我们也可以看到进出元素的时间和过程图中的访问过程是一样的。

总结

总的来说,BFS多用于寻找最短路径的问题,DFS多用于快速发现底部节点。以后若有时间再贴几道相关的题目上来。

作者:Leo-Yang
原文都先发布在作者个人博客:http://www.leoyang.net/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利

BFS和DFS详解以及java实现(转载)的更多相关文章

  1. BFS和DFS详解以及java实现

    前言 图在算法世界中的重要地位是不言而喻的,曾经看到一篇Google的工程师写的一篇<Get that job at Google!>文章中说到面试官问的问题中几乎有一半的问题都可以用图的 ...

  2. BFS和DFS详解

    BFS和DFS详解以及java实现 前言 图在算法世界中的重要地位是不言而喻的,曾经看到一篇Google的工程师写的一篇<Get that job at Google!>文章中说到面试官问 ...

  3. 事件驱动模型实例详解(Java篇)

    或许每个软件从业者都有从学习控制台应用程序到学习可视化编程的转变过程,控制台应用程序的优点在于可以方便的练习某个语言的语法和开发习惯(如.net和java),而可视化编程的学习又可以非常方便开发出各类 ...

  4. Myeclipse Templates详解(一) —— Java模板基础

    目录 Templates简介 MyEclipse自带Templates详解 新建Template 自定义Template 因为自己比较懒,尤其是对敲重复代码比较厌恶,所以经常喜欢用快捷键和模板,Mye ...

  5. Heapsort 堆排序算法详解(Java实现)

    Heapsort (堆排序)是最经典的排序算法之一,在google或者百度中搜一下可以搜到很多非常详细的解析.同样好的排序算法还有quicksort(快速排序)和merge sort(归并排序),选择 ...

  6. 二叉搜索树详解(Java实现)

    1.二叉搜索树定义 二叉搜索树,是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值: 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根 ...

  7. Java AtomicInteger类的使用方法详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 首先看两段代码,一段是Integer的,一段是AtomicInteger的,为以下: public class Samp ...

  8. java 流操作对文件的分割和合并的实例详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 java 流操作对文件的分割和合并的实例详解 学习文件的输入输出流,自己做一个小的示例,对文件进行分割和合并. 下面是代 ...

  9. springboot扫描自定义的servlet和filter代码详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 这几天使用spring boot编写公司一个应用,在编写了一个filter,用于指定编码的filter,如下: /** ...

随机推荐

  1. Execl导出

    1.ExeclUtil.java public class ExcelUtil { public static <T> HSSFWorkbook exprotExcel(String ti ...

  2. 后台异常 - sql语句查询出的结果与dao层返回的结果不一致

    问题描述 sql语句查询出的结果与dao层返回的结果不一致 问题原因 (1)select 中,查询的列名称重复,数据出现错乱 (2)使用不等号,不等号(!=,<>),查询出来的结果集不包含 ...

  3. MS yc

    # word - operate标题栏 菜单栏 工具栏 页面 状态栏 字体阴影 背景色 着重号 项目符号 数字编码 格式刷

  4. Django - installing mysqlclient error: mysqlclient 1.3.13 or newer is required; you have 0.9.3

    环境 Deepin Linux 15.11 Django 2.2 pymysql0.9.3 原因 因为用pymysql替换了默认的mysqlclient,Django官方推荐的数据库API drive ...

  5. C++-POJ1020-Anniversary Cake[搜索][dfs]

    #include <set> #include <map> #include <cmath> #include <queue> #include < ...

  6. update_jz首项V5.0-Tutorial

    What's New: 增加了4个对话框,用于展示信息.归并条目.剔除条目 增加了可视化统计图形中每个科室(柱形)的统计总数 可视化图形一些颜色调整(无奈在省份很多的条件下一些颜色还不易区分) 下面是 ...

  7. Django_类视图

    1. View 2. tamplate view 3. ListView

  8. selenium的错误截图

    在自动化测试过程中,测试执行期间需要收集获取截图信息,一方面为了错误调试代码,一方面也为了和开发沟通, 获取当前的截图 save_screenshot是获取当前截图的方法,以百度首页为例,打开百度首页 ...

  9. 【Python】摄氏度与华氏度互相转化

    Python入门程序,大家可以举一反三,进行各种转换,比如单位转化,货币转化等等,自行发挥即可! 原理:  代码: Tempstr=input("请输入带有符号的温度值:\n")# ...

  10. PTPX-功耗分析总结

    使用PrimeTime PX进行功耗分析有两种:一种是平均功耗的分析Averaged power analysis,一种是Time-based power analysis.   电路的功耗主要有两种 ...