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

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

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

  

深度优先搜索

迷宫搜索

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

  如下图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. Linux 环境下一些常用的命令(二)

    11. chown命令 "chown"命令就是改变文件拥有者和所在用户组.每个文件都属于一个用户组和一个用户.在你的目录下,使用"ls -l",你就会看到像这样 ...

  2. SpriteKit:在场景过渡中暂停动画

    Pausing Scenes During a Transition 你应该意识到两个重要的SKTrnsition属性在场景之间的过渡中. 它们是pausesIncomingScene和pausesO ...

  3. 我的第一个RootKit,支持XP、Vista、Win7、Win8 RTM 32位

    只有写过一个BootKit,才能比较深刻的理解其整个过程与机制,也能加深对Windows系统引导各个过程的熟悉和理解. 我写的这个bootkit,暂时还没想到一个比较好的名字,它 1.  支持xp到w ...

  4. android解析网络json数据(1)

    1.首先获得url,传入URL类,利用URL的openconnection方法,获得URLConnection,去的输入流,进行操作,具体代码如下: public class NetConnectio ...

  5. JAVA面向对象-----main方法详解

    JVM看不懂的可以跳过,这里不做过多解释,(^__^) 嘻嘻-- 主函数是静态的 public static void main(String[] args){ } 主函数是什么:主函数是一个特殊的函 ...

  6. Oracle 执行计划(Explain Plan) 说明

    如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,看看SQL的每一步执行是否存在问题. 如果一条SQL平时执行的好好的,却有一天突然性能很差,如果排除了系统资源和阻塞的原因,那么基本可以 ...

  7. Latex居中

    居中文本 环境:\begin{center} 第一行\\第二行\\...第n行 \end{center}.可以用\\[长度]来插入可以省略的额外行间距.在一个环境内部,可以用命令\centering来 ...

  8. Download all Apple open source OS X files at once

    While it is well known that Mac OS X contains open source code, how to access and download that sour ...

  9. Dynamics CRM2013/2015 插件注册工具登录后无法显示assembly列表问题的解决办法二

    本篇接前面的一篇博文:http://blog.csdn.net/vic0228/article/details/47079717,前篇提供了一种解决方案,将本机系统的语言切换成英文即可,今天再来介绍第 ...

  10. Transform介绍(Unity3D开发之二)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=491 可能unity中接触较早的 ...