学习笔记
学习书目:《算法图解》- Aditya Bhargava


文章目录

  • 图简介
  • 图是啥
  • 广度优先搜索
    • 寻找最短路径
    • 队列
  • 实现图
  • 实现算法
    • 运行时间

图简介

今天是五一,假如我要从家出发去公园玩,现在可去公园的公交车路线如下:

现在,我想找一条换乘最少的线路,该使用什么样的算法呢?

我们先找出一步就能到达的地方,显而易见,一步能到达A、B;再找出两步能到达的地方,经过简单寻找,我们发现两步能到达E、D、C三个地;第三步呢?可以看出第三步可以到达公园和E。很好!此时我们就找到了换乘最少的路线:家–1-->路–>A–3路–>E–5路–>公园

这种问题被称为最短路径问题。我们要找出最短路径,这可能是前往朋友家的最短路径,也可能是国际象棋中把对方将死的最少步数。解决最短路径问题的算法被称为广度优先搜索。

我们解决这个问题时,用了两个步骤:

(1)使用图来建立问题模型

(2)使用广度优先搜索解决问题

图是啥

图模拟了一组连接,比如可像下图一样表示小黄欠我钱:

我们再看一幅更复杂的图:

可以看到这幅图由节点组成,一个节点可能与众多节点直接相连,这些节点被称为邻居。比如,我是小黄的邻居,但奶奶不是小黄的邻居;奶奶既是我的邻居,又是大白的邻居;但是,奶奶没有邻居,因为虽然有指向她的箭头,却没有从她出发的箭头。这种图叫做有向图,其中的关系是单向的。无向图则没有箭头,直接相连的节点互为邻居。

我们看到,下面两个图是等价的:

广度优先搜索

广度优先搜索是一种用于图的查找算法,可帮助回答两类问题。

第一类问题:从节点A出发,有前往节点B的路径吗?

第二类问题:从节点A出发,前往节点B的哪条路径最短?

假如我是一位作者,我想在我的Twitter的朋友列表里找一位编辑。我的想法很简单,先在朋友里找有没有编辑,没有的话就在朋友的朋友里寻找,再没有的话,就在朋友的朋友的朋友里寻找…以此类推

现在我有3个朋友:

我先创建一个朋友名单:

['Huang', 'Hei', 'Bai']

然后依次检查我的3个朋友是否是编辑。假如我没有朋友是编辑,那么我就必须在朋友的朋友中寻找:

比如,我发现Huang不是编辑,那我就把它的朋友Write和Tim加入我的朋友名单,并把Huang从名单中剔除:

['Hei', 'Bai', 'Write', 'Tim']

使用这种算法将搜遍我的整个人际关系网,直到找到编辑。这就是广度优先搜索算法。

寻找最短路径

由我在Twitter的朋友列表里找编辑的例子中,我们已经回答了广度优先搜索的第一个问题(从节点A出发,有前往节点B的路径吗?)现在,我们就要回答第二个问题,即哪位编辑是离我关系最近。比如,我的朋友和我是一度关系,我朋友的朋友和我是二度关系。在我看来,一度关系胜过二度关系。因此,我要现在一度关系中寻找编辑,没有的话,再从二度关系中寻找编辑,以此类推。

需要注意的是,我们必须把一度关系查找完,才能查找二度关系。比如,我必须先查找完Huang, Hei, Bai才能查找Write等二度关系。

以我们刚刚建立的朋友名单为例,一度关系在二度关系之前加入名单:

['Hei', 'Bai',' Write', 'Tim']

我们按顺序依次检查名单中的每个人,看看他是否是编辑。这将先在一度关系中查找,再在二度关系中查找,因此找到的是关系最近的编辑。

注意!只有按顺序查找才能找到与我关系最近的编辑。换句话说Bai先于Tim加入名单,就要先检查Bai。有一个可实现这种目的的数据结构,那就是队列

队列

队列类似于栈,你不能随机地访问队列中的元素。队列只支持两种操作:入队和出队。如果我将A和B加入队列,先加入队列的A也将先出队,而后加入的B则会后出队。

队列是一种先进先出(First In First Out,FIFO)的数据结构,而栈是一种后进先出(Last In First Out,LIFO)的数据结构。

实现图

现在,我们将用散列表来表达这种我-->Huang的关系,并用python代码来实现图:

graph = {}
graph['me'] = ['Huang', 'Hei', 'Bai']
graph['Huang'] = ['Write', 'Tim']
graph['Bai'] = ['Tim']
graph['Hei'] = ['Black', 'Ada']
graph['Write'] = []
graph['Tim'] = []
graph['Black'] = []
graph['Ada'] = []

我们看到Write、Tim、Black、Ada没有邻居,因为只有指向它们的箭头,却没有从它们出发的箭头。

实现算法

python代码:

from collections import deque#判断谁是编辑
def person_is_edit(name):return name[-1] == 'a'#假设名字最后一个字母是a就是编辑#查找某人的关系列表中谁是编辑
def search(name):search_queue = deque()search_queue += graph[name]searched = []#记录已经检查过的人,防止低效率和无限循环while search_queue:person = search_queue.popleft()if person not in searched:if person_is_edit(person):print('I find you {}!'.format(person))return Trueelse:search_queue += graph[person]searched.append(person)return Falsesearch('me')

控制台输出:

I find you Ada!

我们看到,我们在上面的python代码中加入了一个已搜索名单searched,这是为了防止循环和低效率。比如,Huang和Bai都有一个朋友Tim,但是我们只需要检查一次Tim,否则重复查询就是做了无用功。

并且如果出现下面这种情况,我们就会进入死循环:

所以,在检查一个人是否是编辑之前,确认此人是否被检查过,就十分重要了。

运行时间

如果我在我的关系网中搜寻编辑,那就意味着我沿着每条边前行,因此运行时间至少是O(边数)。这里,我们还使用了一个队列,其中包含要检查的每个人。将一个人添加到队列需要的时间是固定的,即为O(1),因此对每个人都这样做需要的总时间为O(人数)。所以,广度优先搜索的运行时间为O(人数 + 边数),这通常写作O(V + E),其中V 为顶点数,E 为边数。

小白的算法初识课堂(part6)--广度优先搜索相关推荐

  1. 小白的算法初识课堂(part7)--狄克斯特拉算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 狄克斯特拉算法 具体步骤实现 术语 跳蚤市场 具体步骤实现 负权边 python实现 狄克斯特拉算法 在上一个 ...

  2. 小白的算法初识课堂(part9)--SHA及Simhash算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 安全散列算法(SHA) 在学SHA算法之前,我们先回顾一下前几个Blog所学的散列函数. 散列函数是这样的一个函数,即无 ...

  3. 小白的算法初识课堂(part8)--贪婪算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 教室调度问题 集合覆盖问题 近似算法 代码实现 NP完全问题 教室调度问题 假如我是一个学校的校长,我们学校有 ...

  4. 小白的算法初识课堂(part5)--散列表

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 散列函数 防止重复 冲突 性能 填装因子 散列函数 散列函数是这样的一个函数,即无论你给它什么样的数据,它都还 ...

  5. 小白的算法初识课堂(part4)--快速排序

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 分而治之 在这里,我想通过2个例子介绍一种著名的递归式问题解决方法–分而治之(D&C) 分蛋糕 假如,我要分一块 ...

  6. 小白的算法初识课堂(part3)--递归

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 递归 基线条件和递归条件 栈 调用栈 递归调用栈 递归 首先,我们看一段代码: def print_num(m ...

  7. 小白的算法初识课堂(part2)--选择排序

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 选择排序 内存工作原理 数组 链表 读取 索引 插入 删除 是常见的数组和链表操作的运行时间 选择排序 pyt ...

  8. 小白的算法初识课堂(part1)--二分查找法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 二分查找法 算法是一组完成任务的指令,任何代码片段都可视为算法.二分查找是一种算法,其输入是一个有序的元素列表(必须有序 ...

  9. 算法简介:层层递进----广度优先搜索(BFS)

    算法简介:层层递进----广度优先搜索(BFS) 算法简介 算法简介 BFS算法思想: 首先以一个未被访问过的顶点作为起始顶点,访问其所有相邻的顶点,然后对每个相邻的顶点,再访问它们相邻的未被访问过的 ...

最新文章

  1. chsop 兼容jquery(解决与transport.js冲突)
  2. 【bzoj2751】[HAOI2012]容易题(easy) 数论,简单题
  3. 「PKUWC2018」Minimax
  4. 随机生成100万个数,排序后保存在文件中
  5. 利用 sys.sysprocesses 检查 Sql Server的阻塞和死锁
  6. 透露|Java学习的最后一点小秘密
  7. 如何快速实现移动端短视频功能?
  8. 创作一个数字人,总共分几步?(下)
  9. One year ago begininginginginging!
  10. qt designer 自定义插件找不到指定的模块_go与qt的新酒老瓶
  11. struts2漏洞修复
  12. CentOS配置DHCP服务器
  13. 凸透镜成像实验软件_凸透镜成像6道例题(含详答)
  14. 文章下载:关于窗宽窗位调节非常有用的论文《DICOM 医学图像窗口变换的加速算法》...
  15. 大地高、正高和正常高及高程异常
  16. RFID-Si24R1芯片基于Android 4.4平台的kernel驱动
  17. PS 将图片渐变透明
  18. window的mysql开机自动启动
  19. Unity开发 Photon Pun 多人游戏组件
  20. Java IO中涉及到的哪些类以及哪些设计模式

热门文章

  1. 机器学习——决策树的三种学习方法
  2. cron 12点执行_Linux中得循环调度任务执行
  3. php调用linux摄像头,Linux_在Linux操作系统上使用摄像头,我的公家笔记本的摄像头一直 - phpStudy...
  4. Runnable和Thread基础---多线程学习笔记(二)
  5. SpringBoot入门:新一代Java模板引擎Thymeleaf(理论)
  6. 不止性能优化,移动端 APM 产品研发技能
  7. junit No tests found matching Method
  8. SecureCRT登陆Centos 6.4乱码问题
  9. 超级详细的教程 一步步教你Vue项目中使用axios如何进行参数拼接
  10. 机房系统(三)——【充值 退卡 】