迪克斯特拉算法主要分四個步驟:
- 找到“最便宜”的節點(可在最短時間內到達的節點)。
- 更新該節點的鄰居節點的開銷。
- 重複這個過程,直到對圖中每個節點都做了。
- 計算最終路徑。
這個算法的核心理念是:找到圖中最便宜的節點,並確保沒有到該節點更便宜的路徑。 (所以需要注意的是如果你的圖包含負權邊,就不能用這個算法,因爲這會導致已經處理過的節點更新。)
假設我現在有上面的一張圖,計算A->F的最小權重。
步驟一:
從A可以到B,C,F。相應的權重爲:
A->B | 8 |
A->C | 10 |
A->F | 100 |
步驟二:
由步驟一得出由A->B爲當前的最便宜節點,然後找到它相鄰的節點:
B->D | 10 |
B->E | 70 |
由此可以更新A->D和A->E的權重:
A->D | 18 |
A->E | 78 |
步驟三:
重複這個操作:
C->E:
C->E | 30 |
更新最短權重:
A->D | 18 |
A->E | 40 |
A->F:
A->F | 100 |
當前最短權重爲:
A->D | 18 |
A->E | 40 |
A->F | 100 |
由D->F可以得到65,A->D爲18,更新權重表:
A->E | 40 |
A->F | 83 |
由E->F可以得到45,A->E爲40,更新權重表:
A->F | 83 |
步驟4:
最後就可以得到它的最小權重路徑:A->B->D->F:83
代碼實現:
import java.util.*;
class Node {
String name;
int val;
Map<String, Node> map;
public Node(String name, int val) {
this.name = name;
this.val = val;
}
public Node(String name) {
this.name = name;
this.val = val;
}
public Node() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public Map<String, Node> getMap() {
return map;
}
public void setMap(Map<String, Node> map) {
this.map = map;
}
public static void main(String[] args) {
Node A = new Node("A");
//構建A
Map<String, Node> map = new HashMap<>();
map.put("B", new Node("B", 8));
map.put("F", new Node("F", 100));
map.put("C", new Node("C", 10));
A.setMap(map);
//構建B
Node B = A.getMap().get("B");
map = new HashMap<>();
map.put("D", new Node("D", 10));
map.put("E", new Node("E", 70));
B.setMap(map);
//構建C
Node C = A.getMap().get("C");
map = new HashMap<>();
map.put("E", new Node("E", 30));
C.setMap(map);
//構建D
Node D = A.getMap().get("B").getMap().get("D");
map = new HashMap<>();
map.put("F", new Node("F", 65));
D.setMap(map);
//構建BE
Node BE = A.getMap().get("B").getMap().get("E");
map = new HashMap<>();
map.put("F", new Node("F", 45));
BE.setMap(map);
//構建CE
Node CE = A.getMap().get("C").getMap().get("E");
map = new HashMap<>();
map.put("F", new Node("F", 45));
CE.setMap(map);
//記錄存值
Map<String, Integer> DateMap = new HashMap<>();
//隊列
List<Node> list = new ArrayList<>();
//獲取A節點下的所有節點
getListNode(list, A);
//記錄A節點下的值(可能A-F就是最短路徑)
int count = list.size();
//只要列表不爲空
while (list.size() > 0) {
//每次減一
--count;
Node node = list.get(0);
//獲取這個這個節點的子節點
List<Node> chiNode = new ArrayList<>();
getListNode(chiNode, node);
//只記錄A到子節點值
if (DateMap.get("A" + node.getName()) == null && count >= 0) {
DateMap.put("A" + node.getName(), node.getVal());
}
if (!chiNode.isEmpty()) {
for (Node n : chiNode) {
if (DateMap.get("A" + n.getName()) != null) {
if (DateMap.get("A" + n.getName()) > (DateMap.get("A" + node.getName()) + n.getVal())) {
DateMap.put("A" + n.getName(), (DateMap.get("A" + node.getName()) + n.getVal()));
}
} else {
//添加值
DateMap.put("A" + n.getName(), node.getVal() + n.getVal());
DateMap.put(node.getName() + n.getName(), n.getVal());
}
}
}
//獲取這個節點下的子節點
getListNode(list, node);
//刪除
list.remove(0);
}
System.out.println(DateMap.get("AF"));
}
public static void getListNode(List<Node> list, Node node) {
Map<String, Integer> map = new HashMap<>();
if (node.getMap() != null) {
//獲取這個節點的所有子節點
for (String name : node.getMap().keySet()) {
map.put(name, node.getMap().get(name).getVal());
}
//排序
List<Map.Entry<String, Integer>> arrayList = new ArrayList<>(map.entrySet());
Collections.sort(arrayList, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o1.getValue().compareTo(o2.getValue());
}
});
//添加節點到末尾
for (Map.Entry<String, Integer> entry : arrayList) {
list.add(node.getMap().get(entry.getKey()));
}
}
}
}
再來一個圖試試:
import java.util.*;
class Node {
String name;
int val;
Map<String, Node> map;
public Node(String name, int val) {
this.name = name;
this.val = val;
}
public Node(String name) {
this.name = name;
this.val = val;
}
public Node() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public Map<String, Node> getMap() {
return map;
}
public void setMap(Map<String, Node> map) {
this.map = map;
}
public static void main(String[] args) {
Node A = new Node("A");
//構建A
Map<String, Node> map = new HashMap<>();
map.put("B", new Node("B", 10));
map.put("D", new Node("D", 20));
map.put("C", new Node("C", 10));
A.setMap(map);
//構建B
Node B = A.getMap().get("B");
map = new HashMap<>();
map.put("F", new Node("F", 5));
map.put("E", new Node("E", 20));
B.setMap(map);
//構建C
Node C = A.getMap().get("C");
map = new HashMap<>();
map.put("F", new Node("F", 20));
C.setMap(map);
//構建D
Node D = A.getMap().get("D");
map = new HashMap<>();
map.put("E", new Node("E", 30));
map.put("G", new Node("G", 100));
D.setMap(map);
//構建BE
Node BE = A.getMap().get("B").getMap().get("E");
map = new HashMap<>();
map.put("G", new Node("G", 50));
BE.setMap(map);
//構建BF
Node BF = A.getMap().get("B").getMap().get("F");
map = new HashMap<>();
map.put("G", new Node("G", 20));
BF.setMap(map);
//構建CF
Node CF = A.getMap().get("C").getMap().get("F");
map = new HashMap<>();
map.put("G", new Node("G", 20));
CF.setMap(map);
//構建CE
Node DE = A.getMap().get("D").getMap().get("E");
map = new HashMap<>();
map.put("G", new Node("G", 30));
DE.setMap(map);
//記錄存值
Map<String, Integer> DateMap = new HashMap<>();
//隊列
List<Node> list = new ArrayList<>();
//獲取A節點下的所有節點
getListNode(list, A);
//記錄A節點下的值(可能A-F就是最短路徑)
int count = list.size();
//只要列表不爲空
while (list.size() > 0) {
//每次減一
--count;
Node node = list.get(0);
//獲取這個這個節點的子節點
List<Node> chiNode = new ArrayList<>();
getListNode(chiNode, node);
//只記錄A到子節點值
if (DateMap.get("A" + node.getName()) == null && count >= 0) {
DateMap.put("A" + node.getName(), node.getVal());
}
if (!chiNode.isEmpty()) {
for (Node n : chiNode) {
if (DateMap.get("A" + n.getName()) != null) {
if (DateMap.get("A" + n.getName()) > (DateMap.get("A" + node.getName()) + n.getVal())) {
DateMap.put("A" + n.getName(), (DateMap.get("A" + node.getName()) + n.getVal()));
}
} else {
//添加值
DateMap.put("A" + n.getName(), node.getVal() + n.getVal());
DateMap.put(node.getName() + n.getName(), n.getVal());
}
}
}
//獲取這個節點下的子節點
getListNode(list, node);
//刪除
list.remove(0);
}
System.out.println(DateMap.get("AG"));
}
public static void getListNode(List<Node> list, Node node) {
Map<String, Integer> map = new HashMap<>();
if (node.getMap() != null) {
//獲取這個節點的所有子節點
for (String name : node.getMap().keySet()) {
map.put(name, node.getMap().get(name).getVal());
}
//排序
List<Map.Entry<String, Integer>> arrayList = new ArrayList<>(map.entrySet());
Collections.sort(arrayList, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o1.getValue().compareTo(o2.getValue());
}
});
//添加節點到末尾
for (Map.Entry<String, Integer> entry : arrayList) {
list.add(node.getMap().get(entry.getKey()));
}
}
}
}
Node A = new Node("A");
//構建A
Map<String, Node> map = new HashMap<>();
map.put("B", new Node("B", 5));
map.put("C", new Node("C", 2));
A.setMap(map);
//構建B
Node B = A.getMap().get("B");
map = new HashMap<>();
map.put("D", new Node("D", 4));
map.put("E", new Node("E", 2));
B.setMap(map);
//構建C
Node C = A.getMap().get("C");
map = new HashMap<>();
map.put("E", new Node("E", 7));
map.put("B", new Node("B", 8));
C.setMap(map);
//構建BE
Node BE = A.getMap().get("B").getMap().get("E");
map = new HashMap<>();
map.put("F", new Node("F", 1));
BE.setMap(map);
Node BD = A.getMap().get("B").getMap().get("D");
map = new HashMap<>();
map.put("F", new Node("F", 3));
map.put("E", new Node("E", 6));
BD.setMap(map);
Node BDE = A.getMap().get("B").getMap().get("D").getMap().get("E");
map = new HashMap<>();
map.put("F", new Node("F", 1));
BDE.setMap(map);
//構建CF
Node CE = A.getMap().get("C").getMap().get("E");
map = new HashMap<>();
map.put("F", new Node("F", 1));
CE.setMap(map);
Node CB = A.getMap().get("C").getMap().get("B");
map = new HashMap<>();
map.put("D", new Node("D", 4));
map.put("E", new Node("E", 2));
CB.setMap(map);
Node CBD = A.getMap().get("C").getMap().get("B").getMap().get("D");
map = new HashMap<>();
map.put("F", new Node("F", 3));
map.put("E", new Node("E", 6));
CBD.setMap(map);
Node CBDE = A.getMap().get("C").getMap().get("B").getMap().get("D").getMap().get("E");
map = new HashMap<>();
map.put("F", new Node("F", 1));
CBDE.setMap(map);
Node CBE = A.getMap().get("C").getMap().get("B").getMap().get("E");
map = new HashMap<>();
map.put("F", new Node("F", 1));
CBE.setMap(map);
OK~迪克斯特拉算法的實現!!!!