本文兼参考自《算法导论》及《算法》。

  以前一直不能够理解深度优先搜索和广度优先搜索,总是很怕去碰它们,但经过阅读上边提到的两本书,豁然开朗,马上就能理解得更进一步。

  下文将会用到的一个无向图例子如下:

  

深度优先搜索

迷宫搜索

  在《算法》这本书中,作者写了很好的一个故事。这个故事让我马上理解了深度优先搜索的思想。

  如下图1-1所示,如何在这个迷宫中找到出路呢?方法见图1-2.

  

  图1-1 等价的迷宫模型

  探索迷宫而不迷路的一种古老办法(至少可以追溯到忒修斯和米诺陶的传说)叫做Tremaux搜索,如下图所示。要探索迷宫中的所有通道,我们需要:

  1)选择一条没有标记过的通道,在你走过的路上铺一条绳子;

  2)标记所有你第一次路过的路口和通道;

  3)当来到一个标记过的路口时,用绳子回退到上个路口;

  4)当回退到的路口已没有可走的通道时继续回退。

  绳子可以保证你总能找到一条出路,标记则能保证你不会两次经过同一条通道或同一个路口。

  

  图1-2 Tremaux探索

深度优先搜索

  《算法》作者给出的Java代码如下:

 public class DepthFirstSearch
{
private boolean[] marked;
private int count; public DepthFirstSearch(Graph G, int s)
{
marked = new boolean[G.V()];
dfs(G, s);
} private void dfs(Graph G, int v)
{
marked[v] = true;
count++;
for(int w : G.adj(v))
{
if(!marked[w])
{
dfs(G, w);
}
}
} public boolean marked(int w)
{
return marked[w];
} public int count()
{
return count;
}
}

DFS.java

  具体例子如下图1-3:

  

  图1-3 使用深度优先探索的轨迹,寻找所有和顶点0连通的顶点

寻找路径

  《算法》作者给出的Java代码如下:

 public class DepthFirstPaths
{
private boolean[] marked; // Has dfs() been called for this vertex?
private int[] edgeTo; // last vertex on known path to this vertex
private final int s; // source
public DepthFirstPaths(Graph G, int s)
{
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
this.s = s;
dfs(G, s);
} private void dfs(Graph G, int v)
{
marked[v] = true;
for (int w : G.adj(v))
if (!marked[w])
{
edgeTo[w] = v;
dfs(G, w);
}
} public boolean hasPathTo(int v)
{
return marked[v];
} public Iterable<Integer> pathTo(int v)
{
if (!hasPathTo(v)) return null;
Stack<Integer> path = new Stack<Integer>();
for (int x = v; x != s; x = edgeTo[x])
path.push(x);
path.push(s);
return path;
}
}

DFS.java

  

  图1-4 pathTo(5)的计算轨迹

  

  图1-5 使用深度优先搜索的轨迹,寻找所有起点为0的路径

广度优先搜索

迷宫搜索

   深度优先搜索就好像是一个人在走迷宫,广度优先搜索则好像是一组人在一起朝各个方向走这座迷宫,每个人都有自己的绳子。当出现新的叉路时,可以假设一个探索者可以分裂为更多的人来搜索它们。当两个探索者相遇时,会合二为一(并继续使用先到达者的绳子)。如下图2-1:

  

  图2-1 广度优先的迷宫搜索

广度优先搜索

  《算法》作者给出的使用广度优先搜索查找图中的路径的Java代码如下:

 public class BreadthFirstPaths
{
private boolean[] marked; // Is a shortest path to this vertex known?
private int[] edgeTo; // last vertex on known path to this vertex
private final int s; // source public BreadthFirstPaths(Graph G, int s)
{
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
this.s = s;
bfs(G, s);
} private void bfs(Graph G, int s)
{
Queue<Integer> queue = new Queue<Integer>();
marked[s] = true; // Mark the source
queue.enqueue(s); // and put it on the queue.
while (!q.isEmpty())
{
int v = queue.dequeue(); // Remove next vertex from the queue.
for (int w : G.adj(v))
if (!marked[w]) // For every unmarked adjacent vertex,
{
edgeTo[w] = v; // save last edge on a shortest path,
marked[w] = true; // mark it because path is known,
queue.enqueue(w); // and add it to the queue.
}
}
} public boolean hasPathTo(int v)
{
return marked[v];
} public Iterable<Integer> pathTo(int v)
// Same as for DFS.
}

BFS.java

  一个例子如下:

  

  图2-2 使用广度优先搜索寻找所有起点为0的路径的结果

  

  图2-3 使用广度优先搜索的轨迹,寻找所有起点为0的路径

  具体代码已经托管到Github.

"《算法导论》之‘图’":深度优先搜索、宽度优先搜索(无向图、有向图)的更多相关文章

  1. 挑战程序2.1.5 穷竭搜索>>宽度优先搜索

    先对比一下DFS和BFS         深度优先搜索DFS                                   宽度优先搜索BFS 明显可以看出搜索顺序不同. DFS是搜索单条路径到 ...

  2. 【算法入门】广度/宽度优先搜索(BFS)

    广度/宽度优先搜索(BFS) [算法入门] 1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略.因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较 ...

  3. BFS算法的优化 双向宽度优先搜索

    双向宽度优先搜索 (Bidirectional BFS) 算法适用于如下的场景: 无向图 所有边的长度都为 1 或者长度都一样 同时给出了起点和终点 以上 3 个条件都满足的时候,可以使用双向宽度优先 ...

  4. 算法基础⑦搜索与图论--BFS(宽度优先搜索)

    宽度优先搜索(BFS) #include<cstdio> #include<cstring> #include<iostream> #include<algo ...

  5. 层层递进——宽度优先搜索(BFS)

    问题引入 我们接着上次“解救小哈”的问题继续探索,不过这次是用宽度优先搜索(BFS). 注:问题来源可以点击这里 http://www.cnblogs.com/OctoptusLian/p/74296 ...

  6. [宽度优先搜索] FZU-2150 Fire Game

    Fat brother and Maze are playing a kind of special (hentai) game on an N*M board (N rows, M columns) ...

  7. 【BFS宽度优先搜索】

    一.求所有顶点到s顶点的最小步数   //BFS宽度优先搜索 #include<iostream> using namespace std; #include<queue> # ...

  8. 宽度优先搜索--------迷宫的最短路径问题(dfs)

    宽度优先搜索运用了队列(queue)在unility头文件中 源代码 #include<iostream>#include<cstdio>#include<queue&g ...

  9. 搜索与图论②--宽度优先搜索(BFS)

    宽度优先搜索 例题一(献给阿尔吉侬的花束) 阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫. 今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔 ...

随机推荐

  1. python 3 dict函数 神奇的参数规则

    >>> dict({1:2},2=3)SyntaxError: keyword can't be an expression>>> dict({1:2},**{2: ...

  2. Dynamics CRM EXCEL导入数据字段类型为选项集时的注意事项

    在开始先展示下CRM的导入数据涉及选项集字段时的一个问题 下图是选项集字段的属性 下图是我要导入的excel中的列值,可以看出列明和字段名是一致的,而列值却不是选项集中已有的选项 在导入校验时,只要字 ...

  3. 22 Notification 通知栏代码

    结构图: MainActivity.java package com.qf.day22_notification; import android.app.Activity; import androi ...

  4. Struts 2 之拦截器

    拦截器概述 Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP(Aspect Oriented Progr ...

  5. ENVI自带的非监督分类测试情况

    最近写了两个关于遥感图像的简单的非监督分类算法KMEAN和ISODATA,发现结果和ENVI的一直有差异,而且还蛮大的,找了好久也没有找到原因.于是用PS自己绘制了一个简单的图像用于测试.如图1所示, ...

  6. 同步图计算:GraphLite的安装和使用

    http://blog.csdn.net/pipisorry/article/details/51350908 export HADOOP_HOME=/usr/local/hadoop-2.6.4ex ...

  7. 剑指Offer——网易笔试之不要二——欧式距离的典型应用

    剑指Offer--网易笔试之不要二--欧式距离的典型应用 前言 欧几里得度量(euclidean metric)(也称欧氏距离)是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的 ...

  8. 深入理解MyBatis框架的的配置信息

    面对一个框架,最重要的不是说回用其代码就可以了,我们需要了解其思想,这样才能更快更好的掌握这个框架.而对于一个框架,最重要的就是其配置文件的作用及功能了.下面,我就来谈一谈我今天遇到的这个MyBati ...

  9. 运用 三种 原生 谷歌 阿里 解析和生成json

    三种类生成JSON数据方法 JSON(原生): 第一种 JSONStringer和JSONObject区别在于添加对象时是按顺序添加的比如说 JSONStringer 添加 a:1 b:2 c:3那么 ...

  10. 【翻译】Ext JS 6.2 早期访问版本发布

    原文:Announcing Ext JS 6.2 Early Access 非常开心,Sencha Ext JS 6.2早期访问版本今天发布了.早期访问版本的主要目的是为了让大家进行测试并评估Ext ...