从头开始复习算法之让你彻彻底底的搞清楚BFS和DFS

最近又有点学不进去了,不知道是不是天气热的缘故哈,没办法只好写一点算法来保持学习的路线不间断咯。 关于BFS和DFS,这是我们在面试的时候经常会遇到的两个基础算法,为什么说基础呢?因为它理解了之后才10行左右的代码,你说基础不基础?

一、 BFS

BFS,全称:Breadth First Search。中文翻译为广度优先搜索或者是宽度优先搜索,具体是怎么回事儿呢?
首先来用下面一颗的树来引入一下广度优先搜索的实现步骤:


如上图所示,我们先用一棵树来引入广度优先搜索。为什么要用树呢?因为我觉得树来入门是最简单的,也是最容易理解的。
首先按照广度优先搜索的方法,我们就应该就是这样来搜索:
A->B->C->D->E->F
或者是:
A->C->B->F->D->E

我先来从结果分析上面的遍历结果,我发现广度优先搜索有这样的特点对:

  • 先从根节点处查找,然后一层一层的往下查找。
    怎么理解呢?首先查找A也就是第一层,然后再查找BC,也就是第二层,最后查找DEF 也就是第三层。
  • 查找子层的时候,应该按照父层的顺序来查找子层。
    怎么理解呢?首先查找A节点,然后查找A的子层B和C,当然我们在查找A子层的时候先来查找的B节点,那么在查找B的子节点的时候就要优先查找B的子节点。同理如果第二层里面先查找C也是一样。
  • 广度优先搜索的搜索结果并不唯一。

通过上面的结果来分析,其实我们很容易发现广度优先算法有点队列的意味在里面。
怎么理解呢?来看下面一套图:



首先新建一个队列,先去查找一下树的根结点,并且将根结点A放入队列中。



移出节点A,并且把A的子节点加入到队列中。

移出节点B,并且把B的子节点加入到队列中。

...
依次类推,就将所谓的最后的广度优先搜索的路线给画出来了:


最终结果

通过前面的探究,我们大概晓得了广度优先搜索的一个大致流程,也差不多知道其实现的规则有点类似于队列。此时可能有人会说了,你只是讲解了一个简单的树,而我们看到的BFS一般是用图来展示的。
针对上面的疑问,我们首先来画一个无向图。

其实在我的理解里面:图和树最大的区别就是树有专门的起点,但是图却没有固定的起点。我们可以从任何一个点做起点来去搜索,例如:从A点出发,搜索结果是:
A->B->C->D->E->F
从E点出发:
E-> C->D->F->A->B
...

这样,我们其实就可以把之前树的那一套类似到图中,只不过图没有起点罢了,并且将树的子层换成了与指定节点相连的节点。这样类比之下也可以用队列来实现。具体的代码如下:

首先我们建立一张图:

let graph = {
    'A':['B','C'],
    'B':['A','C','D'],
    'C':['A','B' ,'D','E'],
    'D':['B','C','E'],
    'E':['C','D','F'],
    'F':['E']
}

然后BFS的实现代码如下:

function bfs(graph,startPoint){
    let queue = [];
    let result = []

    queue.push(startPoint);
    result.push(startPoint);

    while(queue.length>0){
        let point = queue.shift();
        let nodes = graph[point];
        for(let node of nodes){
            if(result.includes(node)) continue;
            result.push(node);
            stack.push(node);
        }
    }
    return result

}

二、DFS

好了,前面谈到了广度优先搜索,那么什么是深度优先搜索呢?
首先我来用一套图集来辅助理解深度优先搜索的历程:


首先选定起点为A(起点是任意的),然后从A出发,搜索到B



然后再从B出发,搜索到C



再从C出发搜索到E

再从E出发搜索到D,此时整张图都没有与D相连但是没被搜索到的节点了,此时该怎么办呢?

如果搜索到没有可以搜索的节点,就应该回溯到最近存在相邻可以的节点处继续搜索。

总之,我对于深度优先搜索的理解就是:

  • 访问顶点A
  • 依次从A的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和A有路径相通的顶点都被访问;
  • 若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

这样看来,深度优先是不是有一点栈的意思在里面呢?怎么理解哦,我们再来看下面一套图。


首先我们从A出发,将节点A移入栈,然后将A移出栈



将A的子节点C,B移入栈内。



然后将B移出栈,并将与B相连的D,C节点移入栈内

然后将C移出栈,将与C相连的D,E节点移入栈内

然后将E移出栈,将与E相连的F,D节点移入栈内



然后将D移除栈,我们发现并没有可用的新节点了,就不再移入直接移出。

移出F节点

当我在移除新D节点的时候,发现D节点已经被移出过了。此时我们就将该节点丢弃,同样后面的节点也是一样。最后就完成了深度优先搜索。

通过上面的图级演示是不是很容易就能看出来深度优先搜索的实现原理呢?下面我们用代码的方式来去演示一下其原理吧:

function dfs(graph,startPoint){
    let stack = [];
    let result = []

    stack.push(startPoint);
    result.push(startPoint);

    while(stack.length>0){
        let point = stack.pop();
        let nodes = graph[point];
        for(let node of nodes){
            if(result.includes(node)) continue;
            result.push(node);
            stack.push(node);
        }
        

    }
    return result

}

说在最后

说了这么多,感觉午休的时间都所剩无几了,感觉自己还是没有把这部分的内容讲清楚。本来想额外写一点关于广度优先搜索的更深层次的用法的(作为很多图形结构的基础,其实应用还是比较广的),但我还是需要睡的呀!反正中午看来是说不完了。关于还没写完的内容呢,我这里提及一下:
如果相邻节点之间的距离相同的情况下,我们想求广度优先搜索的最短路径怎么来求呢?
如果相邻节点之间的距离不同呢?我们应该如何来计算呢
如果明天中午有机会的话,我会细细讲解这一块的内容的,敬请期待哦!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266