算法简介
Dijkstra算法是用于非负有向图的单源最短路径算法。该算法的核心思想是广度优先搜索,具体可以参看维基百科的动图。
算法思路
首先建立两个链表,openList和closeList,用于维护当前进度,前者表示待检查的点,后者表示未检查的点。再建立一个数组dis,用于表示当前点到起点s的花费/距离,dis一开始全为无穷大。(如果是将距离起点的花费作为node类的属性则可以不用单独建立dis数组。)算法首先从将起点s加入openList开始,然后进入循环,每次从openList中取出一个点,取出原则是openList中dis值最小的点,并将取出点放入closeList中。然后依据该点依据一定查找规则进行邻接点查找,将邻接点依次加入openList中,并依据一定规则设置/更新这些邻接点的dis值。接着再次进行循环。查找规则是只要是取出点的邻接点,并且不在closeList之中的点,都属于满足条件的要加入openList的邻接点。dis值的更新规则是:如果当前邻接点在openList中,则其dis值必不为无穷,假设为dis1,那么通过dis[邻接点]=dis[取出点]+cost[取出点到邻接点]
的公式,我们可以计算出当前取出点到邻接点的dis值dis2,然后比较dis1和dis2,如果dis1小,则说明取出点到该邻接点的花费大,不可取,因此不更新。若dis2小,则说明取出点到该邻接点的花费更小,因此要更新,并且把该邻接点的父节点设为取出点;另外一种情况,如果邻接点不在openList中,则直接通过公式计算dis值,并把该邻接点的父节点设为取出点。循环结束条件是当终点e被加入closeList中或openList为空时,循环结束。前者对应找到了最短路径,后者对应没找到。获得最短路径的方法就是从终点开始,依次沿着节点的父节点属性寻找,直至到达起点,则该路径为最短路径。
算法伪代码
dijkstra(graph, sNode, eNode){
openList.add(sNode) //For openList, PriorityQueue is recommended
isFind = false;
while(!openList.isEmpty()){
node = openList.getMinDisNode();
closeList.add(node); //For closeList, HashSet is recommended
if(node == eNode){
isFind = true;
break;
}
findAdjacentNode(node);
}
if(isFind){
getTrace();
}
}
findAdjacentNode(curNode){
for(node : getAdjacentNodeList(curNode)){
if(!closeList.contains(node)){
tempDis = dis[curNode]+cost(curNode2node);
if(dis[node]>tempDis){
dis[node] = tempDis;
node.father = curNode;
}
}
openList.add(node);
}
}