【JAVA演算法】圖論演算法 -- Dijkstra演算法
寫在前面:
我也是一名java語言的愛好者,僅以此文作為學習的記錄,對於文中出現的程式碼規範,程式碼格式,演算法效率等問題,希望各路大神不吝賜教,在下感激不盡。同是學習的同學也同樣希望互相交流,取長補短。
——zsferrier@126.com
Dijkstra演算法是貪心演算法最好的例子,貪婪演算法一般分階段求解一個問題,在每個階段它都把出現的當作最好的去處理。
首先給出資料型別
//節點所儲存的資料域
class Vertex{
public List<Integer> adjacency;//鄰接表
public boolean known; //標記
public int dist; //距離出發點的距離
public Vertex path;//路徑
public int vname;//節點編號
public Vertex(){
known = false;
dist = MaxLen;
path = null;
}
}
鄰接表儲存與該節點鄰接所有節點的邊資訊,不直接相鄰的節點距離為MaxLen(預定義,MaxLen=1000表示不距離不可達)
known標記節點是否已知。
dist為此節點當前距離原點的距離MaxLen表示不可達。
path記錄路徑上的上一個節點。
vname為節點編號。
dijkstra分階段求解,在每個階段,選擇一個節點v,它在所有的unknown節點中具有最小的dist值,納入已知節點。根據該節點的鄰接域(邊的值cvw)來計算其他unknown狀態下的鄰接點w的dist,與Vw的原dist值比較,若v.dist+cvw<w.dist,則更新。
賦權圖
下面給出Dijsktra演算法虛擬碼:
void dijkstra( Vertex s )
{
for each Vertex v
{
v.dist = INFINITY;
v.known = false;
}
s.dist = 0;
while( there is an unknown distance vertex )
{
Vertex v = smallest unknown distance vertex;
v.known = true;
for each Vertex w adjacent to v if( !w.known )
{
DistType cvw = cost of edge from v to w;
if( v.dist + cvw < w.dist )
{
// Update w
decrease( w.dist to v.dist + cvw ); w.path = v;
}
}
}
}
JAVA語言實現:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
/**
* @param args
*/
//節點所儲存的資料域
class Vertex{
public List<Integer> adjacency;//鄰接表
public boolean known; //標記
public int dist; //距離出發點的距離
public Vertex path;//路徑
public int vname;//節點編號
public Vertex(){
known = false;
dist = MaxLen;
path = null;
}
}
private static int MaxLen = 1000;//表示不可達
//有權圖,使用鄰接表來表示圖。
private static Vertex[] verArray = new Vertex[7];
//這個函式用來判斷還有沒有unknown distance vertex
public static boolean judge(){
for (Vertex v : verArray) {
if(v.known==false){
return true;
}
}
return false;
}
//這個函式用來返回再unknown中最小的distance vertex
public static Vertex smallestVertex(){
int num = 0;
int value = MaxLen;
for (int i = 0; i < verArray.length; i++) {
if((verArray[i].known==false)&&(verArray[i].dist<value)){
num = i;
value = verArray[i].dist;
}
}
return verArray[num];
}
public static void dijkstra(int s){
verArray[s].dist = 0;//起點的dist為零
while(judge()){
Vertex vtex = smallestVertex();
vtex.known = true;
for (Integer i : vtex.adjacency) {
if(!verArray[vtex.adjacency.indexOf(i)].known){
if (vtex.dist+i<verArray[vtex.adjacency.indexOf(i)].dist) {
//Update
verArray[vtex.adjacency.indexOf(i)].dist = vtex.dist+i;
verArray[vtex.adjacency.indexOf(i)].path = vtex;
}
}
}
}
}
//輸出路徑函式
public static void printGraph(Vertex v){
if(v.path!=null){
printGraph(v.path);
}
System.out.print("V"+v.vname+" ");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//初始化
verArray[0] = new Main().new Vertex();
verArray[1] = new Main().new Vertex();
verArray[2] = new Main().new Vertex();
verArray[3] = new Main().new Vertex();
verArray[4] = new Main().new Vertex();
verArray[5] = new Main().new Vertex();
verArray[6] = new Main().new Vertex();
verArray[0].adjacency = new ArrayList<Integer>(Arrays.asList(0,2,MaxLen,1,MaxLen,MaxLen,MaxLen));
verArray[0].vname = 0;
verArray[1].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,0,MaxLen,3,10,MaxLen,MaxLen));
verArray[1].vname = 1;
verArray[2].adjacency = new ArrayList<Integer>(Arrays.asList(4,MaxLen,0,MaxLen,MaxLen,5,MaxLen));
verArray[2].vname = 2;
verArray[3].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,2,0,2,8,4));
verArray[3].vname = 3;
verArray[4].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,MaxLen,MaxLen,0,MaxLen,6));
verArray[4].vname = 4;
verArray[5].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,MaxLen,MaxLen,MaxLen,0,MaxLen));
verArray[5].vname = 5;
verArray[6].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,MaxLen,MaxLen,MaxLen,1,0));
verArray[6].vname = 6;
//起點從v0開始
dijkstra(0);
for (Vertex v : verArray) {
System.out.print("到節點V"+v.vname+"的最短路徑為: ");
printGraph(v);
System.out.println();
}
}
}
控制檯輸出
這裡注意一點,我定義的Vertex是個內部類,在主函式中如果直接使用new動態申請記憶體的時候會出現這樣的錯誤。
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
No enclosing instance of type Main is accessible. Must qualify the allocation with an enclosing instance of type Main (e.g. x.new A() where x is an instance of Main).
at DijkstraAlg.Main.main(Main.java:75)
報錯位置為 verArray[0] = new Vertex();
這是由於Java中的內部類沒有使用static修飾,其建構函式被認為是一個動態方法,而主函式main為靜態函式,不能直接呼叫,解決的方法為在new Vertex前加上外部類,即:
verArray[0] = new Main().new Vertex();
轉載請標明出處,謝謝 by zsferrier@126.com
相關文章
- 《圖論》——最短路徑 Dijkstra演算法(戴克斯特拉演算法)圖論演算法
- JAVA實現DIJKSTRA演算法Java演算法
- Dijkstra演算法演算法
- 【JAVA演算法】圖論演算法 --求最小生成樹Prim演算法Java演算法圖論
- 圖論演算法圖論演算法
- 最短路演算法之:Dijkstra 演算法演算法
- 【圖論】Floyd演算法圖論演算法
- 圖解Dijkstra演算法+程式碼實現圖解演算法
- 最短路dijkstra演算法演算法
- 貪心演算法Dijkstra演算法
- 最短路 - Dijkstra 演算法演算法
- 最短路徑——Dijkstra演算法和Floyd演算法演算法
- 最短路徑—Dijkstra演算法和Floyd演算法演算法
- 圖的單源最短路徑(Dijkstra演算法)演算法
- Dijkstra演算法和Prim演算法有什麼區別?演算法
- 如何在 Java 中實現 Dijkstra 最短路演算法Java演算法
- 演算法-圖論-拓撲排序演算法圖論排序
- 「圖論」Bron-kerbosch演算法圖論演算法
- 最短路徑之Dijkstra演算法演算法
- Dijkstra 演算法的手動分析演算法
- Dijkstra演算法和Floyd演算法超詳解以及區別演算法
- Dijkstra演算法詳解(樸素演算法+堆最佳化)演算法
- 圖論系列之「讀取圖演算法」圖論演算法
- 圖論與圖學習(二):圖演算法圖論演算法
- 圖論演算法遍歷基礎圖論演算法
- 演算法-圖論-最小生成樹演算法圖論
- 單源最短路徑複習--Dijkstra演算法和Floyd演算法演算法
- 最短路徑問題 (dijkstra演算法)演算法
- 單源最短路徑-Dijkstra演算法演算法
- 單源最短路徑 -- Dijkstra演算法演算法
- dijkstra最短路演算法模板(雙源)演算法
- Dijkstra演算法及正確性分析演算法
- 圖論-二分圖匹配匈牙利演算法圖論演算法
- 程式碼隨想錄演算法訓練營第64天 | 圖論:Floyd 演算法+A * 演算法演算法圖論
- 演算法資料結構 | 圖論基礎演算法——拓撲排序演算法資料結構圖論排序
- 資料結構與演算法——迪傑斯特拉(Dijkstra)演算法資料結構演算法
- 演算法手記(2)Dijkstra雙棧算術表示式求值演算法演算法
- 《演算法導論》演算法