《图解算法》读书笔记(六) 广度优先搜索

章节内容

  • 学习新的数据结构图来建立网络模型
  • 学习广度优先搜索
  • 学习有向图和无向图
  • 学习拓扑排序

图由多个节点和节点之间的连线组合而成。
一个节点可能与众多节点直接相连,这些节点被称为邻居。

广度优先搜索

广度优先搜索(BFS)是一种图算法,用于解决两个节点的最短路径问题;两个节点是否想通。
最短路径问题比如:

  • 编写国际跳棋,计算最少走多少步可以获胜
  • 编写拼写检查器,计算最少编辑几个地方可以将错误单词改正确
  • 根据你的人际关系网络找到关系最近的医生

查找最短路径

在人际关系网中,一度关系胜过二度关系,二度关系胜过三度关系,以此类推。
所以我们在搜索关系最近的医生时,应优先搜索一度关系,再检查二度关系。
我们需要顺序地将人际关系添加到一个数据结构中,然后进行检查。有一个可实现这种目的的数据结构就是队列。

队列

队列的工作原理和现实中的队列完全相同。
队列只支持两种操作,入队和出队(现实中的插队不算);并且先入队的先出队(FIFO),而之前学习的栈是先进后出

实现图

图是由节点和节点间的连线组成的,我们可以把节点间的连线当做一种映射关系,所以我们可以用用散列表来实现图。
比如表示人机关系图的python代码:

graph = {}
graph["you"] = ["alice", "bob", "claire"]
graph["bob"] = ["anuj", "peggy"]
graph["alice"] = ["peggy"]
graph["thom"] = ["jonny"]

上面代码中的关系是单向的,jonny是thom的邻居,但是没有指向jonny的人,所以jonny没有邻居。这种单向的图被称为有向图。
反之,直接相连的节点互为邻居则成为无向图。

实现BFS算法

我们学习了队列的工作原理,也学习了图的数据结构实现,接下来就可以实现BFS算法:

def searchDoctor(name):
      search_queue = deque()
      search_queue += graph[name]
      searched = []    //用这个数组记录里检查过的人,防止重复检查产生死循环
      while search_queue:
            person = serach_queue.popleft()
            if not person in searched:   //当这个人没有检查过
                  if person_is_doctor(person):
                        print person + " is a doctor"
                        return true
                  else:
                        search_queue += graph[person]
                        searched.append(person) //将这个人标记为已检查
       return false

searchDoctor("you")     

小结

  1. 广度优先搜索指出是否有从A到B的路径
  2. 如果有,广度优先搜索将找出最短路径
  3. 面临类似于寻找最短路径问题,可尝试使用图来建立模型,再使用广度优先搜索来解决问题
  4. 有向图中的边为箭头,箭头的方向指定了关系的方向
  5. 无向图中的边不带箭头,其中的关系是双向的
  6. 队列是先进先出的
  7. 栈是后进先出的
  8. 你需要按加入顺序检查搜索列表的人,否则找到的就不是最短路径,因此搜索列表必须是队列
  9. 对于检查过的人,务必不要再去检查,否则可能导致无线循环
原文地址:https://www.cnblogs.com/prelude1214/p/13611328.html