算法图解5 - 图和广度优先搜索

Posted Android开发中文站

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法图解5 - 图和广度优先搜索相关的知识,希望对你有一定的参考价值。


一直以来总是把「数据结构」和「算法」分的很开,认为图,链表都应该属于数据结构领域。然后当看到书的后面章节时,才发现有些东西并不需要明显的界限。
一、图是什么?
图模拟一组连接。
是不是觉得很抽象?别着急,我们打个比方,朋友一起打牌,我们要记录谁欠谁钱:

欠钱关系可能如下所示:

算法图解5 - 图和广度优先搜索

好了,是时候引出我们的概念:
  1. 图由节点 node 和边 edge 组成。
  2. 一个节点可能与众多节点直接相连,这些节点被称为邻居。
    在前面的欠钱图中,Rama 是 Alex 的邻居。Adit 不是 Alex 的邻居,因为他们不直接相连。但 Adit 既是 Rama 的邻居,又是 Tom 的邻居。
  3. 图用于模拟不同的东西是如何相连的。
二、图的表示
我们可以用散列表来表示图,那么在 JS 中呢,当然就是 Hash Map 了。

算法图解5 - 图和广度优先搜索

  
    
    
  
let graph =  new Map();
graph. set( 'jartto', [ 'alice''bob''claire']);
graph. set( 'alice', []);
graph. set( 'bob', []);
graph. set( 'claire', []);

graph. get( 'jartto');  // ["alice", "bob", "claire"]
来看看输出:
关于图,有几点需要注意:
  1. 图中的每个节点都需要表示;
  2. 键值对的添加顺序对结果没有影响,因为散列表是无序的;
三、有向图和无向图
要区别这两个概念,我们先来看下面这张图:

算法图解5 - 图和广度优先搜索

有向图:有指向邻居的箭头,其中的关系是单向的。
无向图:undirected graph 没有箭头,直接相连的节点互为邻居。
无向图中的边不带箭头,其中的关系是双向的。
四、图的实现
说了这么多,那么如何代码实现呢?

算法图解5 - 图和广度优先搜索

  
    
    
  
// 定义散列表
let graph =  new Map();
graph. set( 'jartto', [ 'alice''bob''claire']);
graph. set( 'bob', [ 'anuj''peggy']);
graph. set( 'alice', [ 'peggy']);
graph. set( 'claire', [ 'thom''jonny']);
graph. set( 'anuj', []);
graph. set( 'peggy', []);
graph. set( 'thom', []);
graph. set( 'jonny', []);

// 查询函数
function search(name{
   let queue = [];
   let searched = [];
  queue = queue.concat(graph. get(name));

   while (queue.length >  0) {
    person = queue.shift();
     if (!searched.includes(person)) {
       if (isSeller(person)) {
        console.log(`${person}  is a mango seller`);
         return  true;
      }  else {
        queue = queue.concat(graph. get(person));
        searched.push(person);
      }
    }
  }
   return  false;
}

// 检查人的姓名是否以m结尾:如果是,他就是芒果销售商。
function isSeller(name{
   return name[name.length -1] ==  'm';
}

search( 'jartto');
五、广度优先搜索
广度优先搜索是一种用于图的查找算法,可帮助回答两类问题。
  1. 从节点 A 出发,有前往节点 B 的路径吗?
  2. 从节点 A 出发,前往节点 B 的哪条路径最短?
解决最短路径问题的算法被称为广度优先搜索。
我们来打个比方,朋友是一度关系,朋友的朋友是二度关系。像下面这张图:


在广度优先搜索的执行过程中,搜索范围从起点开始逐渐向外延伸,即先检查一度关系,再检查二度关系。
广度优先搜索不仅查找从A到B的路径,而且找到的是最短的路径。
六、广度优先搜索使用场景
  1. 编写国际跳棋 AI,计算最少走多少步就可获胜;
  2. 编写拼写检查器,计算最少编辑多少个地方就可将错拼的单词改成正确的单词,如将 READED 改为 READER 需要编辑一个地方;
  3. 根据你的人际关系网络找到关系最近的医生。
七、运行时间
如果你在你的整个人际关系网中搜索芒果销售商,就意味着你将沿每条边前行(记住,边是从一个人到另一个人的箭头或连接),因此运行时间至少为 O (边数)。
你还使用了一个队列,其中包含要检查的每个人。将一个人添加到队列需要的时间是固定的,即为 O(1),因此对每个人都这样做需要的总时间为 O (人数)。
所以,广度优先搜索的运行时间为 O (人数 + 边数),这通常写作 O(V + E ),其中 V 为顶点 vertice 数,E 为边数。
八、扩展:拓扑排序


从某种程度上说,这种列表是有序的。如果任务 A 依赖于任务 B ,在列表中任务 A 就必须在任务 B 后面。这被称为拓扑排序 ,使用它可根据图创建一个有序列表。

以上是关于算法图解5 - 图和广度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章

《图解算法》--快速排序哈希表图广度优先搜索算法

图解算法广度优先搜索

算法图解:广度优先搜索

八数码问题算法,谁有?

图解:深度优先搜索与广度优先搜索

广度优先搜索算法(go)