廣度優先算法適用於計算有向無權圖計算最短路徑。狄克斯特拉算法是有向加權圖計算最小開銷的算法,不適用於負權邊的情況。
下面是代碼示例,起點是start,經過a點權重是6,b點的權重是2,a點到終點fin的權重是1。b點到a點的權重是3,到fin點的權重是5,現在計算從start到fin的最小權重路徑。
package com.teriste.algorithm;
import org.apache.commons.collections.MapUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DijKstraAlgorithm {
//節點關係及權重
public static Map<String,Map<String,Integer>> graph = new HashMap<>();
//每個節點的開銷,從起點到該節點的開銷
public static Map<String,Integer> cost = new HashMap<>();
//每個節點的父節點
public static Map<String,String> parent = new HashMap<>();
//記錄處理過的節點避免重複處理
//public static List<String> processed = new ArrayList<>();
static {
//起點
Map<String,Integer> start = new HashMap<>();
//起點到a點的權重
start.put("a",6);
//起點到b點的權重
start.put("b",2);
graph.put("start",start);
//a點
Map<String,Integer> a = new HashMap<>();
//a到fin點的權重
a.put("fin",1);
graph.put("a",a);
//b點
Map<String,Integer> b = new HashMap<>();
//b到a點的權重
b.put("a",3);
//b到fin點的權重
b.put("fin",5);
graph.put("b",b);
//fin點是終點
graph.put("fin",null);
//-------------------------------
cost.put("a",6);
cost.put("b",2);
//------------------------
parent.put("a","start");
parent.put("b","start");
parent.put("fin",null);
}
//遍歷輸入節點的所有臨近節點,
public void dijKstraCalc(String key){
Map<String,Integer> start = graph.get(key);
if (MapUtils.isEmpty(start)){
return;
}
if (MapUtils.isNotEmpty(start)){
//遍歷臨近節點
for(Map.Entry<String,Integer> entry:start.entrySet()){
if (entry.getValue()==null){
return;
}
/**
* 取出到該臨近節點的權重和cost記錄的到該臨近節點的權重比較,
* 取最小權重存入cost,
* 並記錄到該臨近節點的最小權重的節點記錄到parent散列表
*/
if (null==cost.get(entry.getKey())||entry.getValue()<cost.get(entry.getKey())){
cost.put(entry.getKey(),entry.getValue());
parent.put(entry.getKey(),key);
}
//遞歸遍歷該該節點的臨近節點的臨近節點直到最後一個節點結束
dijKstraCalc(entry.getKey());
}
}
}
}
測試:
package com.teriste.algorithm;
import com.alibaba.fastjson.JSON;
import org.junit.Test;
public class DijKstraAlgorithmTest {
@Test
public void dijKstraCalcTest(){
DijKstraAlgorithm algorithm = new DijKstraAlgorithm();
//輸入起點,開始計算
algorithm.dijKstraCalc("start");
//節點的父子關係
System.out.println("parent:"+JSON.toJSONString(DijKstraAlgorithm.parent));
//到該節點的權重
System.out.println("cost"+JSON.toJSONString(DijKstraAlgorithm.cost));
}
}
參考文獻:《算法圖解》