深度优先搜索

深度优先,顾名思义,只要有路,则一条路走到底,然后回溯,看之前的叉路口是否还有路可选。


一、基本概念

深度优先搜索 是一种图的遍历算法,可用于求单源最短路径。

算法思路


这里写图片描述

看图说话!如上是一个有向图。

  • 假设我们需要找到从1到4结点的路径。那么从结点1开始遍历,然后递归的遍历所有与1相邻的结点。所以,第一,我们需要构建图的邻接矩阵(建模很重要),并初始化。

  • 为了避免遍历完1结点后,在跳到2结点时,又往回遍历1结点。所以,第二,我们需要用一个数组visited来标记 已遍历过 的结点(简单的hash表)。

  • 前面讲过,深度优先其实就是先一条路走到黑。那么,在从1到2后,就应该是在2的邻接结点中选择一个结点(此前已将1和2结点标记为了已遍历),假如选择3,那么接下来就是从3的邻接结点中选择一个结点,如上只能选择4(visited[1] != 0),因此1-2-3-4便是1到4的一条路径。

  • 如此,便完成了一次深度搜索。 如果任务重新修改为找到从1到4节点的最短路径,虽然通过上述过程,我们已经找到了一条路径。但是此时,并不能确定此为最短。因为,在之前的叉路口,还有其他路径可选时,比如在节点2的时候,除了3这个选择,我们还可以选择5,因此,我们还需要重新回到2节点,然后看看如果接下来我们选择5,会不会有可能也可以到达4,并且路程缩短。 基于这个想法,进入下一个步骤。

  • 首先是在4结点的基础上回溯到3结点,由于3只有一个往外地指向,所以继续回溯到2结点。(注意,回溯的时候需要将此前标记过的结点去除标记,即将4和3去除标记)。在回溯到2结点时,发现还有一条可走的路径,即跳转到5,然后接下来的过程便是重复上述步骤。最后发现新的路径: 1-2-5-3-4 。在此,基于结点2的所有可能路径便已全部遍历完。于是再从2回溯到1(并将2标记为未遍历),将1其余的邻接结点按照上述步骤重复。


二、举例说明

1. 求最短路径

假设有5个城市,城市之间的道路情况如下图所示,1和2之间的单向箭头表示只能从1到2,箭头上面的数字表示城市之间的距离。要求计算从1到5之间的最短距离。


这里写图片描述

  1. 构建邻接矩阵:


    这里写图片描述

  2. 初始一个数组用于记录每个节点是否被遍历。visited[]

  3. 在当前结点处,判断与其他结点是否有通路(-1表示没有)。例如,假设当前在结点1,判断与其他结点之间的关系,只需要遍历一个一维数组就可以了(第一行)。

  4. 发现 [1,2] 位置 > 0 时,则表示1和2之间有通路,如果 visited[2] = 0 则表示节点2没有被访问过,那么也就代表着此时站在节点1时,可以从节点1过渡到节点2, 然后再执行 visited[2] = 1 以标识节点2被访问了。

  5. 通过第4步,到达了节点2。此时,由于节点2不是目的节点,则需要站在节点2的位置,继续“选路”,也就是遍历第二行,从第二行中找到可选节点。剩下的过程就是重复步骤4和步骤5,直到没有路可选了 或者 已到达目的节点。然后就是回溯,也就是从最深一层的递归中退出来时,将之前访问过的节点重新标记为未访问,然后就是再重复之前过程。。。(表述有点不清晰,代码说话= =)

代码如下:

/*
    深度优先搜索算法 
    作者:Zoo
    时间:2016年4月16日12:45:19 
*/ 

#include <iostream> // for cout
#include <string.h> // for memset

#define N 100

using namespace std;

int city_n ;        //城市的数量
int road_n ;        //道路的数量
int minDis = -1;    //最短路程 -1 表示此数值无效 
int visited[N];     //已经路过的城市 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值