1 Dijkstra描述与分析
1.1 算法描述
Dijkstra最短路径算法,具体地说,应该是一种单点到多点(one to many)的最短路径搜索算法,因为它从起点开始搜索时,总是优先搜索和展开当前离起点路径最短的节点,直至搜索到目标点时结束搜索。
有人说,Dijkstra算法是一种贪心的算法,因为每次搜到当前节点时,总是任性地判定“当前看来的局部最优解(在当前已搜索空间上的最短路径path(s,....,t))是全局最优解(全图空间上的最短路径path(s,.....t))”。
我们知道,图的遍历分为深度优先搜索和广度优先搜索两种。其实假设任意相邻两个节点之间的阻抗均为单位1时(方便理解),Dijkstra最短路径算法则演变成了宽度优先搜索算法:从起始点向四周层层展开,最终遇到终点t时终止搜索。
1.2 算法证明
无论从贪心算法还是宽度优先遍历算法的角度理解它,Dijkstra算法算是一种盲目的搜索算法,所以我们还是会怀疑它搜索结果的正确性。有些事情如果很难证明它是正确的,那么我们试图揭穿它是错误的--反证法。
Dijkstra搜索过程:从当前起始点s开始搜索,搜着搜着...,终于在当前搜索扩展空间上遇到目标点t时,结束搜索,求出最短路径为path(s,...,d)。那么如果继续扩大范围进行搜索时,有没可能找到更短的由s至目标点t的路径呢?假设继续扩大范围搜索,经过了节点u然后遇到了目标点t,存在着候选路径path(s,....u..,t)<path(s,...,d)。path(s,....u..,t) = path(s,..,u)+path(u,..,t)。又已知搜索规则是"优先搜索和展开当前离起点路径最短的节点",所以path(s,..,u)>path(s,...,d),很明显得出path(u,..,t)小于0的结论,而前提条件是任意两节点间没有负权值的,所以假设不成立。这也是为什么Dijkstra算法得在没有负权值的条件下work的原因。
自Dijkstra算法创造出来至今的50多年时间里,虽然相继出现了些加速优化的算法,但均是以dijkstra算法为基础的,可以说dijkstra是网络最优路径算法的开山之作,当然Dijkstra其人的伟大之作不在此多表。
2 Dijkstra搜索空间存在的问题
假设每个节点表示一个城市,起始点S为武汉,目标点T为北京的搜索节点展开过程如下:
其中节点的标号表示从起始点节点开始搜索依次展开的序号。按Dijkstra“离起始点路径最短的当前点为优先搜索展开准则”,先搜索到附近的岳阳、合肥、南昌、南京等城市,然后搜索到了长沙、郑州等城市,最后一定是在搜索到目的地北京之前,先搜索到了广州节点,由于武汉-广州较武汉-北京稍短些。心理认知上告诉我们,岳阳、长沙等方向明显是会和目标点方向相悖的搜索节点,所以在这个搜索过程中,算法遍历了很多“冤枉徒劳”的路。
正所谓“方向错了,再努力也没用”。那么有什么策略可以减少这种“南辕北辙”的现象呢,或者说直觉上优先加速搜索方向更靠谱的节点?
3 A*算法
自1959年,前图灵奖获得者发明Dijkstra算法后。终于在近10年后的1968年,由斯坦福研究所的Nilsson扩展了其算法,提出了著名的A*算法。而A*算法正是以“优先搜索直觉上方向靠谱的节点”为策略来减少搜索空间达到加速搜索目标点的目的,其搜索空间如下:
Dijkstra算法是以起始点为中心,离起始点路径最短的当前点为优先准则,层层向外进行展开的搜索策略。 而A*算法在Dijkstra基础上进行了扩展,同样以起始点为中心,但是以离起始点和目标点路径的近似之和为最短的当前点(估价函数之一)为优先准则,层层向外进行展开的搜索策略。
从图搜索算法的角度上思考:Dijkstra算法更近似宽度优先搜索算法,而A*算法更近似深度优先搜索算法。回忆初中课本关于圆与椭圆的定义,不难近似描述出Dijkstra算法与A*算法的搜索空间如下:
搜索耗时是与搜索的空间范围成正比的,所以两者算法的耗时对比:也即是两焦点为R的椭圆与半径为R的面积近似比。
参考