这是算法学习的第二篇博客,本文将聚焦于图搜索相关的算法。
图
所谓的图(Graph)由节点和边构成,节点代表变量,边表示相互关系,通常具有一定的权重。图的搜索算法可以解决一些基本的问题,比如最短路径问题。
广度优先搜索
广度优先搜索的特征从起点开始,由近及远进行广泛地搜索。下面我们定义一个图(如下图),这是个无向图,我们从某个节点出发分别进行广度优先搜索和深度优先搜索。
1 | graph = { |
深度优先搜索
深度优先搜索和广度有限搜索一样,都是对图进行搜索的算法,目的都是从起点开始到达指定顶点(终点)。深度优先搜索会沿着一条路径不断往下搜索直到不能再继续为止,然后再折返,开始搜索下一条候补路径。
1 | # 深度优先搜索 |
最短路径
下面我们看一些求最短路径的算法,贝尔曼-福特算法,Dijkstra算法,还有A-star算法。求下面的图 $A$ 到其它节点的最短路径。
贝尔曼-福特算法(Bellman-ford)
贝尔曼-福特算法是求最短路的一种算法,该算法是以松弛操作为基础,集估计的最短路径值逐渐被更加精确的值代替,直至得到最优解。该算法的缺点是时间复杂度较高 $O(|V||E|)$,其中 $|V|$ 代表节点数量,$|E|$代表边的数量。
1 | import math |
Dijkstra算法
Dijkstra算法可以看作是广度优先搜索在有权图上的推广,其是通过为每个顶点保留到目前为止的最短路径工作的。最初的Dijkstra算法没有通过小优先队列实现,时间复杂度为 $O(|V|^2)$(其中 $|V|为图的顶点个数$)。通过斐波那契堆实现的Dijkstra算法的时间复杂度为 $O(|E|+|V|log|V|)$ (其中 $|E|$ 为边数),对于不含负权的有向图,Dijkstra是已知的最快单源最短路径算法。
1 | import heapq |
虽然Doijkstra算法和Bellman ford算法一样可以求解有向图中的最短路径问题,但是当图中有负数权重时,Dijkstra算法无法得到正确的答案。
A-star 算法
A-star算法是有Dijkstra发展而来的算法。Dijkstra算法会从离起点近的顶点开始,按顺序求出起点到各个顶点的最短路径。也就是说一些离起点较远的顶点的最短路径也会被计算出来,但这部分是无用的。与之不同的是,A-star算法会先估计一个值,然后利用这个值省去无用的计算。
下面我们详细地介绍一下A-star算法在路径规划上面的应用,不同前面的简单路径图,我们这里使用了一个“硬核”的迷宫图,其中红色箭头表示起点位置,蓝色箭头表示终点位置,黑色的点代表障碍物,障碍物是不能直接穿过的。
1 | import matplotlib.pyplot as plt |