从头开始复习算法之我们来简单的应用一下BFS

今天中午的时候呢?我简单介绍了一下广度优先搜索和深度优先搜索。关于这两个概念吧,如果不知道的时候会感觉很难 但是一旦理解了这个东西 就感觉很简单。
既然今天谈到了BFS,并且好多人都说BFS是很多算法的基础,那么我就从基础开始说起 简单谈一下BFS的应用吧。

一、 求BFS两点之间的路径

看了标题,可能有点不明白对吧,先看我们的图



首先我们根据上一篇文章的想法来写一下BFC的代码吧:

// 图
let graph = {
    'A':['B','C'],
    'B':['A','C','D'],
    'C':['A','B','D','E'],
    'D':['B','C','E'],
    'E':['C','D','F'],
    'F':['E']
}
function dfs(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
}

上面就是上一篇文章深入原理讲的BFS的代码,如果有不懂的,可以返回上一篇文章进行专研,我这里就不多加赘述了。
在一篇文章讲到BFS,我们是从一颗树引入的。我当时讲到:在广度优先搜索之下,图就是没确定起点的树。例如我们将起来设定成A,其实我们也能把树形结构给画出来:



如果我们能画出这个树的话,其实就能明白我说得的意思。如果我们设定的起点是A,那么F到A点的路径就是:F->E->C->A;B点到A的路径就是B->A
我们来修改一下前面的代码吧:

// 别问我为什么修改了一下上面的代码。其实一个意思
// 其实我在为明天中午的复习set做准备,顺便复习了一下api 哈哈
function bfs(graph,startPoint){
    let queue = [];
    let result = new Set();
    let tree = {};

    queue.push(startPoint);
    result.add(startPoint);
    tree[startPoint] = ""

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

function shortDistance(tree,point){
    let node = point
    let distance = [point]
    while(tree[node]!=""){
        node = tree[node];
        distance.push(node);
    }
    return distance;
}

怎么理解上面的代码呢?
很简单,就是将每个数据在出栈的时候记录一下他的父节点是谁?如下图所示:

户口薄

如上图所示,第一段代码就相当于给每一个元素建立了一个户口薄,每个人的身份信息全部都填写到了本本上面,如果想找找到路径,就直接从当前节点开始盘问。例如:E到A的路径,就可以如下操作:

就能找出E->C->A的路径。

二、 求BFS的最短路径/距离

上面用一个例子简单的介绍了一个广度深度优先算法的两个点的路径,但是其实很容易就会发现得到的答案并不是唯一的,比如就上面的条件来说,我也可以画成这样的树 也能满足需求:



如上所示,其实这样也是能满足需求的,针对这种比较不唯一的情况 我就大胆了再给其加上限定条件。如下图所示:



如上图所示,A到C的路径 一共有A->C和A->B->C。但是A->C的距离是5,A->B->C的距离是3。所以此时的最短路径应该是A->B->C。

具体的排序方式 同样我们用下面的一组套图来解释一下。

同样我们先把A放进容器中。


将A移出容器,并将与A相连的B,C 移入容器内,再比较与B,C相连的距离谁比较近。明显B距离A比较近。

将B移出容易,并且将与B相连的C,D加入容器内,此时我们发现容器内有两个C,而后者的C比前者要小。

image.png

将距离比较小的C和距离比较大的C调换位置,然后移出,并且将与C相连的D,E加入容易内。

同理将容器内比较小的D移出容器,当我们再次将容器内比较小的C和D移出时,发现之前移出的数据里面中已经存在C,D。此时就将C,D给舍弃

最后就这样得到了所谓的最短路径了。来我们用代码来演示一下:

function bfs(graph,startPoint){

    let queue = [];
    let result = {};
    let seen = new Set();

    let distance =  initDistance(graph,startPoint);

    queue.push({distance:0,name:startPoint});
    result[startPoint] ={parent:"",distance:0,};

    while(queue.length > 0){

        let point = queue.shift();
        let dist = point.distance;
        let vertex = point.name;
        seen.add(vertex);
        let nodes = graph[vertex]
        for(let node in nodes){
            if(!seen.has(node)&&dist+nodes[node]<distance[node]) {
                result[node]= {parent:vertex,distance:dist+nodes[node]};
                distance[node] = dist+nodes[node];
                queue.push({distance:dist+nodes[node],name:node});
            }
            
        }
        queue.sort((a,b)=>{
            return a.distance-b.distance;
        })

    }
    console.log(result)
    return result;
}

那么此时我们的数据结构就应该是这个样子了哦:

let graph = {
    'A':{'B':1,'C':5},
    'B':{'A':1,'C':2,'D':3},
    'C':{'A':5,'B':2,'D':4,'E':10},
    'D':{'B':3,'C':4,'E':3},
    'E':{'D':3,'C':10,'F':5},
    'F':{'E':5}
}

说在最后

关于BFS用法呢?其实还是比较简单的。也是只要想通了,写出来还是比较简单的。我这里呢?就简单的写一两个例子来给诸位当一个敲门砖吧。如果之前有研究过第二个问题,其实很容易就发现其实第二个问题就是大名鼎鼎的Dijkstra算法。如果对图有深层次的兴趣,也可以深入了解一下哦 毕竟知道总比不知道好。

好了,好了 中午睡觉的时间真的又被我活生生的写完了,看来今天又没午觉睡了。还是去躺躺一下吧。

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

推荐阅读更多精彩内容