广度优先搜索

首先,先介绍一下什么是图(它们不涉及X轴和Y轴),再介绍第一种图算法——广度优先搜素(breadth-frist search,BFS)。
广度优先搜素让你能够找出两样东西之间的最短距离,不过最短距离的含义有很多!使用广度优先搜索可以:
❑ 编写国际跳棋AI,计算最少走多少步就可获胜;
❑ 编写拼写检查器,计算最少编辑多少个地方就可将错拼的单词改成正确的单词,如将READED改为READER需要编辑一个地方;
❑ 根据你的人际关系网络找到关系最近的医生。

图简介
图是什么,图模拟一组连接。假如你与朋友玩牌,并要模拟谁欠谁钱,可像下面这样指出Alex欠Rama钱。

完整的欠钱图可能类似于下面这样。

Alex欠Rama钱,Tom欠Adit钱,等等。图由节点 (node)和边 (edge)组成。

就这么简单!图由节点和边组成。一个节点可能与众多节点直接相连,这些节点被称为邻居。。在前面的欠钱图中,Rama是Alex的邻居。Adit不是Alex的邻居,因为他们不直接相连。但Adit既是Rama的邻居,又是Tom的邻居。图用于模拟不同的东西是如何相连的。下面来看看广度优先搜索。

广度优先搜索
前面介绍了二分查找,广度优先搜索是一种用于图的查找算法,可帮助回答两类问题。
第一类问题:从节点A出发,有前往节点B的路径吗?
第二类问题:从节点A出发,前往节点B的那条路径最短?

假设你经营着一个芒果农场,需要寻找芒果销售商,以便将芒果卖给他。在Facebook,你与芒果销售商有联系吗?为此,你可在朋友中查找。


这种查找很简单。首先,创建一个朋友名单。

然后,依次检查名单中的每个人,看看他是否是芒果销售商。

假设你没有朋友是芒果销售商,那么你就必须在朋友的朋友中查找。

检查名单中的每个人时,你都将其朋友加入名单。

这样一来,你不仅在朋友中查找,还在朋友的朋友中查找。别忘了,你的目标是在你的人际关系网中找到一位芒果销售商,因此,如果Alice不是芒果销售商,就将其朋友也加入到名单中。这意味着你将在她的朋友、朋友的朋友等中查找。使用这种算法将搜遍你的整个人际关系网,直到找到芒果销售商。这就是广度优先搜索算法。

查找最短路径
再说一次,广度优先搜索可回答两类问题。
第一类问题:从节点A出发,有前往节点B的路径吗?(在你的人际关系网中,有芒果销售商吗?)
第二类问题:从节点A出发,前往节点B的哪条路径最短?(哪个芒果销售商与你的关系最近?)
刚才你看到了如何回答第一类问题,下面来尝试回答第二类问题——谁是关系最近的芒果销售商。例如,朋友是一度关系,朋友的朋友是二度关系。

在你看来,一度关系胜过二度关系,二度关系胜过三度关系,以此类推。因此,你应先在一度关系中搜索,确定其中没有芒果销售商后,才在二度关系中搜索。广度优先搜索就是这样做的!在广度优先搜索的执行过程中,搜索范围从起点开始逐渐向外延伸,即先检查一度关系,再检查二度关系。

你也可以这样看,一度关系在二度关系之前加入查找名单。你按顺序依次检查名单中的每个人,看看他是否是芒果销售商。这将先在一度关系中查找,再在二度关系中查找,因此找到的是关系最近的芒果销售商。广度优先搜索不仅查找从A到B的路径,而且找到的是最短的路径。

注意,只有按添加顺序查找时,才能实现这样的目的。换句话说,如果Claire先于Anuj加入名单,就需要先检查Claire,再检查Anuj。
如果Claire和Anuj都是芒果销售商,而你先检查Anuj再检查Claire,结果将如何呢?找到的芒果销售商并非是与你关系最近的,因为Anuj是你朋友的朋友,而Claire是你的朋友。因此,你需要按添加顺序进行检查。

有一个可实现这种目的的数据结构,那就是队列 (queue)。

队列
 队列的工作原理与现实生活中的队列完全相同。假设你与朋友一起在公交车站排队,如果你排在他前面,你将先上车。队列的工作原理与此相同。队列类似于栈,你不能随机地访问队列中的元素。队列只支持两种操作:入队 和出队 。
 

如果你将两个元素加入队列,先加入的元素将在后加入的元素之前出队。因此,你可使用队列来表示查找名单!这样,先加入的人将先出队并先被检查。队列是一种先进先出 (First In First Out,FIFO)的数据结构,而栈是一种后进先出 (Last In First Out,LIFO)的数据结构。

实现算法
先概述一下这种算法的工作原理。

小结:

  • 广度优先搜索指出是否有从A到B的路径。
  • 如果有,广度优先搜索将找出最短路径。
  • 面临类似于寻找最短路径的问题时,可尝试使用图来建立模型,再使用广度优先搜索来解决问题。
  • 有向图中的边为箭头,箭头的方向指定了关系的方向,例如,rama→adit表示rama欠adit钱。
  • 无向图中的边不带箭头,其中的关系是双向的,例如,ross - rachel表示“ross与rachel约会,而rachel也与ross约会”。
  • 队列是先进先出(FIFO)的。
  • 栈是后进先出(LIFO)的。
  • 你需要按加入顺序检查搜索列表中的人,否则找到的就不是最短路径,因此搜索列表必须是队列。
  • 对于检查过的人,务必不要再去检查,否则可能导致无限循环。

狄克斯特拉算法
继续图的讨论,介绍加权图——提高或降低某些边的权重。介绍狄克斯特拉算法,让你能够找出加权图中前往X的最短路径。介绍图中的环,它导致狄克斯特拉算法不管用。在前一章,你找出了从A点到B点的路径。

这是最短路径,因为段数最少——只有三段,但不一定是最快路径。如果给这些路段加上时间,你将发现有更快的路径。

x下面来看看如何对下面的图使用这种算法。

其中每个数字表示的都是时间,单位分钟。为找出从起点到终点耗时最短的路径,你将使用狄克斯他拉算法。
如果你是用广度优先搜索,将得到下面这条段数最少的路径。

这条路径耗时7分钟。下面来看看能否找到耗时更短的路径!
狄克斯特拉算法包含4个步骤。
(1) 找出“最便宜”的节点,即可在最短时间内到达的节点。
(2) 更新该节点的邻居的开销,其含义将稍后介绍。
(3) 重复这个过程,直到对图中的每个节点都这样做了。
(4) 计算最终路径。

第一步 :找出最便宜的节点。你站在起点,不知道该前往节点A还是前往节点B。前往这两个节点都要多长时间呢?

前往节点A需要6分钟,而前往节点B需要2分钟。至于前往其他节点,你还不知道需要多长时间。

由于你还不知道前往终点需要多长时间,因此你假设为无穷大(这样做的原因你马上就会明白)。节点B是最近的——2分钟就能达到。
第二步 :计算经节点B前往其各个邻居所需的时间。

你刚找到了一条前往节点A的更短路径!直接前往节点A需要6分钟。

对于节点B的邻居,如果找到前往它的更短路径,就更新其开销。在这里,你找到了:
前往节点A的更短路径(时间从6分钟缩短到5分钟);
前往终点的更短路径(时间从无穷大缩短到7分钟)。
第三步 :重复!
重复第一步 :找出可在最短时间内前往的节点。你对节点B执行了第二步,除节点B外,可在最短时间内前往的节点是节点A。

重复第二步 :更新节点A的所有邻居的开销。

你发现前往终点的时间为6分钟!
你对每个节点都运行了狄克斯特拉算法(无需对终点这样做)。现在,你知道:
前往节点B需要2分钟;
前往节点A需要5分钟;
前往终点需要6分钟。

术语
介绍其他狄克斯特拉算法使用示例前,先来澄清一些术语。狄克斯特拉算法用于每条边都有关联数字的图,这些数字称为权重 (weight)

带权重的图称为加权图 (weighted graph),不带权重的图称为非加权图 (unweighted graph)。

要计算非加权图中的最短路径,可使用广度优先搜索 。
要计算加权图中的最短路径,可使用狄克斯特拉算法 。图还可能有环 ,而环类似右面这样。

无向图意味着两个节点彼此指向对方,其实就是环!

在无向图中,每条边都是一个环。狄克斯特拉算法只适用于有向无环图 (directed acyclic graph,DAG)。

术语介绍得差不多了,我们再来看一个例子!这是Rama,想拿一本乐谱换架钢琴。

Alex说:“这是我最喜欢的乐队Destroyer的海报,我愿意拿它换你的乐谱。
如果你再加5美元,还可拿乐谱换我这张稀有的Rick Astley黑胶唱片。”
Amy说:“哇,我听说这张黑胶唱片里有首非常好听的歌曲,我愿意拿我的吉他和架子鼓换这张海报和黑胶唱片。”
Beethoven惊呼:“我一直想要吉他,我愿意拿我的钢琴换Amy的吉他或架子鼓。”
太好了!只要再花一点点钱,Rama就能拿乐谱换架钢琴。现在他需要确定的是,如何花最少的钱实现这个目标。我们来绘制一个图,列出大家的交换意愿。

这个图中的节点是大家愿意拿出来交换的东西,边的权重是交换时需要额外加多少钱。拿海报换吉他需要额外加30美元,拿黑胶唱片换吉他需要额外加15美元。Rama需要确定采用哪种路径将乐谱换成钢琴时需要支付的额外费用最少。为此,可以使用狄克斯特拉算法!别忘了,狄克斯特拉算法包含四个步骤。在这个示例中,你将完成所有这些步骤,因此你也将计算最终路径。动手之前,你需要做些准备工作:创建一个表格,在其中列出每个节点的开销。这里的开销指的是达到节点需要额外支付多少钱。

在执行狄克斯特拉算法的过程中,你将不断更新这个表。为计算最终路径,还需在这个表中添加表示父节点 的列。

这列的作用将稍后介绍。我们开始执行算法吧。
第一步 :
找出最便宜的节点。在这里,换海报最便宜,不需要支付额外的费用。还有更便宜的换海报的途径吗?这一点非常重要,你一定要想一想。Rama能够通过一系列交换得到海报,还能额外得到钱吗?想清楚后接着往下读。答案是不能,因为海报是Rama能够到达的最便宜的节点,没法再便宜了。下面提供了另一种思考角度。假设你要从家里去单位。

如果你走经过学校的路,到学校需要2分钟。如果你走经过停车场的路,到停车场需要6分钟。如果经停车场前往学校,能不能将时间缩短到少于2分钟呢?不可能,因为只前往停车场就需要6分钟。另一方面,有没有能更快到达停车场的路呢?有。

这就是狄克斯特拉算法背后的关键理念:
找出图中最便宜的节点,并确保没有到该节点的更便宜的路径 !回到换钢琴的例子。换海报需要支付的额外费用最少。
第二步 :
计算前往该节点的各个邻居的开销。

现在的表中包含低音吉他和架子鼓的开销。这些开销是用海报交换它们时需要支付的额外费用,因此父节点为海报。这意味着,要到达低音吉他,需要沿从海报出发的边前行,对架子鼓来说亦如此。

再次执行第一步 :下一个最便宜的节点是黑胶唱片——需要额外支付5美元。
再次执行第二步 :更新黑胶唱片的各个邻居的开销。

你更新了架子鼓和吉他的开销!这意味着经“黑胶唱片”前往“架子鼓”和“吉他”的开销更低,因此你将这些乐器的父节点改为黑胶唱片。下一个最便宜的是吉他,因此更新其邻居的开销。

你终于计算出了用吉他换钢琴的开销,于是你将其父节点设置为吉他。最后,对最后一个节点——架子鼓,做同样的处理。

如果用架子鼓换钢琴,Rama需要额外支付的费用更少。因此,采用最便宜的交换路径时,Rama需要额外支付35美元 。现在来兑现前面的承诺,确定最终的路径。当前,我们知道最短路径的开销为35美元,但如何确定这条路径呢?为此,先找出钢琴 的父节点。

钢琴的父节点为架子鼓,这意味着Rama需要用架子鼓来换钢琴。因此你就沿着这一边。

我们来看看需要沿哪些边前行。钢琴 的父节点为架子鼓 。

架子鼓 的父节点为黑胶唱片。

因此Rama需要用黑胶唱片了换架子鼓。显然,他需要用乐谱来换黑胶唱片。通过沿父节点回溯,便得到了完整的交换路径。

小结:

  • 广度优先搜索用于在非加权图中查找最短路径。
  • 狄克斯特拉算法用于在加权图中查找最短路径。
  • 仅当权重为正时狄克斯特拉算法才管用。
  • 如果图中包含负权边,请使用贝尔曼-福德算法。

算法图解——读书笔记06相关推荐

  1. 算法图解读书笔记:附程序

    算法图解通俗易懂,下面是随书练习程序,基于python3 二分法 #二分法 def binary_search(list, item):low = 0high = len(list)-1while l ...

  2. 算法图解 读书笔记(上)

    最近看了一本算法入门书--算法图解. 封面的插画很好玩儿.最吸引我的还是封面里的一句话:向小说一样有趣的算法入门书. 上个封面,大家感受一下: 一.算法简介 1.1 二分查找 一个有序数组中找一个数的 ...

  3. 强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning)

    强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning) 学习笔记: Reinforcement Learning: An Introductio ...

  4. 推荐系统实践读书笔记-06利用社交网络数据

    推荐系统实践读书笔记-06利用社交网络数据 自从搜索引擎谷歌诞生后,大家都在讨论互联网的下一个金矿是什么.现在,几乎所有的人都认为那就是社交网络.根据尼尔森2010年的报告,用户在互联网上22%的时间 ...

  5. 数据之道读书笔记-06面向“自助消费”的数据服务建设

    数据之道读书笔记-06面向"自助消费"的数据服务建设 数据底座建设的目标是更好地支撑数据消费,在完成数据的汇聚.整合.联接之后,还需要在供应侧确保用户更便捷.更安全地获取数据.一方 ...

  6. 《Java8实战》读书笔记06:Parallel Stream 并行流

    <Java8实战>读书笔记06:Parallel Stream 并行流 第7章 并行数据处理与性能 7.1 并行流 7.1.1 将顺序流转换为并行流 7.1.2 测量流性能 7.1.3 正 ...

  7. 算法导论读书笔记(8)

    算法导论读书笔记(8) 目录 计数排序 计数排序的简单Java实现 基数排序 基数排序的简单Java实现 桶排序 计数排序 计数排序 假设 n 个输入元素中的每一个都是介于0到 k 之间的整数,此处 ...

  8. 算法导论读书笔记(7)

    算法导论读书笔记(7) 目录 快速排序 快速排序的简单Java实现 快速排序的性能 最坏情况划分 最佳情况划分 快速排序的随机化版本 比较排序 快速排序 快速排序是一种原地排序算法,对包含 n 个数的 ...

  9. 《漫画算法》读书笔记

    <漫画算法>读书笔记 在图书馆借阅算法书时,看到了一本非常吸引我的算法书--<漫画算法>.算法还能以漫画的方式展示出来吗?我带着我的疑惑翻开了这本书,里面的语言非常接地气,通俗 ...

最新文章

  1. Fiddler抓取手机(app)https包
  2. 算法提高课-搜索-Flood fill算法-AcWing 1098. 城堡问题:flood fill、bfs
  3. ubuntu 安装 mongodb并修改仓库路径
  4. vba mysql连接字符串_分享一个VBA连接mysql数据库的方法
  5. 计算机竞赛女生,我校组队参加 CCPC-WFINAL中国大学生程序设计竞赛女生专场
  6. Android-导航栏特效-新闻类APP(仿iOS版网易新闻今日头条的文字渐变缩放特效)
  7. DPDK Release 19.11
  8. css3学习手册思维导图
  9. 郑州大学python程序设计试题及答案_Python程序设计(胡新明)-中国大学mooc-试题题目及答案...
  10. 计算机应用基础课考试题B,大工《计算机应用基础》课程考试模拟试卷B
  11. 怎么查看笔记本内存条型号_win10怎么查看自己电脑的内存条型号-win7之家·电脑系统下载站...
  12. DBeaver与excel
  13. python上传大文件s3_使用Python boto3上传Windows EC2实例中的文件至S3存储桶中
  14. mht文件打开后显示不正常或乱码问题的排除
  15. 工作的驱动力——成就感
  16. 腾讯Flink实践:实时计算平台Oceanus建设历程
  17. python调用打印机打印pdf_python连接打印机实现打印文档、图片、pdf文件等功能
  18. 【第四章 | 进程同步】《操作系统 慕课版》课后答案 + 复习
  19. 开发调试工具:USB转IIC/I2C/SPI/UART适配器模块可编程开发板
  20. Spring Security + JWT简单配置

热门文章

  1. 联想G50-30出厂win8换win7心得体会,解决鼠标,键盘失灵等问题
  2. QT小控件-遥控按钮
  3. GoWeb 书城项目
  4. 【ESD专题】金属外壳连接器的信号PIN脚需要进行ESD测试吗?
  5. 算法与数据结构 判断选择程序填空 绪论
  6. Infiniband vs 以太网Ethernet 对比
  7. 怎样把计算机放到桌面上,如何将我的电脑图标放在桌面上 - 卡饭网
  8. 中国楼市热度骤降,IT人分析未来房价是涨是跌?
  9. 每日一题——小b和灯泡(数论)
  10. 修改 WSL2 可用内存大小和交换分区大小