《算法图解》读书笔记-05

第四章:图的搜索

要研究图的搜索,首先要讲清楚什么是图;你可以理解为:图就是顶点和顶点之间连接的集合

比如全国的铁路线网,我们将车站抽象为顶点,将连接车站的铁路抽象为车站之间的连接,如果有一套寻路算法,我们就能轻松得知从A车站到B车站怎么走最近,同时还能得知要怎么换乘;

图中顶点之间的连线是可以有权重的(比如车站之间每条铁路的长度不同),连接也可以是单向的(就像生活中的单行道);

根据搜索的策略不同,有广度优先搜索和深度优先搜索;

广度优先搜索和深度优先搜索

所谓广度优先,和深度优先相反;指的是尽可能同时涉猎尽可能多的路径,提高搜索的广度;比如搜索一个堆时,广度优先搜索会逐层遍历搜索,而深度优先搜索会一条路走到黑,每次只访问一个分支直到遇到死角,再返回最近的没有死角的上一级继续搜索;

下面我们基于这张图来详细讲讲两种搜索方式的区别:

a
b
c
d
e
f
g
h
i
j
k
l

如果使用广度优先搜索,则搜索的顺序是:

  1. a
  2. b,c,d
  3. e,f,h,i,j
  4. k,g,l

如果使用深度优先搜索,则搜索的顺序是:

  1. a,b,e,k
  2. f
  3. c,h,j
  4. d,i
  5. j,l

贝尔曼-福特算法

这是一个寻路算法;下面是一个闭环的图,我们将尝试使用这个算法在下面的图中进行寻路;

a
b
c
e
d
f
g

贝尔曼-福特算法的逻辑是:

  • 每条连接两个节点的路径都有权重,节点拥有自己的“值”,表示从起点到该节点的距离;算法开始执行时,起点的值为0,其它节点全部为正无穷;节点的值会随着算法的进行不断更新;
  • 某个节点的值由路径另一端的节点加上路径的权重影响;如果相加的值小于节点的值,则将节点值更新为这个值,否则不变;
  • 循环执行确认节点值的操作,直到所有节点的值都不再更新为止;

算法执行完毕后我们得到了一张标注了每个节点的权重的值,从起点开始每一步都选择最小的节点作为下一步的方向,就能获得从起点到终点的最短距离;

你可能会问:现在知道最短距离了,但是我怎么确定最短路径呢?

实际上路径也是在寻路算法的运行过程中确定的;每个节点值都来自一条路径,这条最后更新了节点值的路径就是激活路径,在寻找最短路径时未激活路径将不被考虑;从终点开始,一步步选择值降低的节点,就可以回溯到起点,经过的路径也就是从起点到重点的最短路径;

设图的定点数为n,边数为m,时间复杂度是 O ( n m ) O(nm) O(nm);但这种算法的问题是:没有办法计算含有非正值权重的图;

狄克斯特拉算法

迪克斯拉特算法也在开始的时候将起点设置为0,将其它所有点设置为正无穷;但两者寻路的部分逻辑有所不同,带来的直观不同就是狄克斯特拉算法可以处理含权重0和负数路径的图;

狄克斯特拉寻路算法的逻辑是:

  • 将顶点下游激活为待选择顶点,并尝试更新更新权重
  • 选择权重最小的待选择顶点作为新的顶点
  • 持续进行这个过程直到所有顶点都被遍历为止

接下来我们得到了一幅激活路径并计算过权重的图,像贝尔曼福特那样回溯算法,就可以找到从起点到任意终点的路径了;

迪克斯拉特寻路算法的时间复杂度是 O ( n 2 ) O(n^2) O(n2),当顶点数为n路径数为m时;

当一个图中存在负数路径时,理论上讲这个图不存在最短路径;贝尔曼-福特算法能直接发现没有最小值,但狄克斯特拉算法会计算出一个错误的结果;

你可能感兴趣的:(算法,数据库,数据结构)