最短路徑(鄰接矩陣)-Dijkstra演算法
阿新 • • 發佈:2019-01-01
Dijkstra演算法又叫作迪傑斯特拉演算法,是利用"貪心法"(在對問題進行求解時,總是做出在當前看來最好的選擇策略)設計演算法的一個成功範例。
適用條件:帶權無環和無負權值
舉個栗子:
Dijkstra演算法的程式碼實現如下:
package com.threeTop.www; import java.util.Stack; /** * 鄰接矩陣儲存方式的Dijkstra演算法 * @author wjgs * */ public class Dijkstra { //通過下標對映元素值 private int[] mapping; //圖的二維陣列 private int[][] matrix; /** * 初始化圖的頂點 * @param vertexes 頂點陣列 */ public Dijkstra(int []vertexes) { int length=vertexes.length; mapping=new int[length]; matrix=new int[length][length]; //圖的二維矩陣 for(int i=0;i<length;i++) { mapping[i]=vertexes[i]; } } /** * 新增具有權值的邊 * @param start * @param end * @param value */ public void addEdge(int start,int end,int value) { int x=-1; int y=-1; //尋找座標 for(int i=0;i<mapping.length;i++) { if(x!=-1&&y!=-1) { break; } if(start==mapping[i]) { x=i; } if(end==mapping[i]) { y=i; } } //判斷頂點是否存在 if(x==-1||y==-1||x>mapping.length-1||y>mapping.length-1) { throw new IndexOutOfBoundsException("邊的頂點不存在!"); } //增加邊的權值 matrix[x][y]=value; } /** * Dijkstra演算法實現到各點的最短路徑 * @param start */ public void dijkstra(int start) { int length =mapping.length; int x=-1; //記錄起始點 for(int i=0;i<length;i++) { if(mapping[i]==start) { x=i; break; } } if(x==-1) { throw new RuntimeException("未找到起始頂點"); } //自動初始化為0,都屬於未得到最短路徑的頂點 int[]s=new int[length]; //儲存v到u的最短距離 int [][] distance=matrix; //儲存x到u最短路徑時u的前一個頂點 int []path=new int[length]; //初始化path陣列 for(int i=0;i<length;i++) { //如果可達就賦值 if(matrix[x][i]>0) { path[i]=x; } else { //不可達,則賦前一個頂點下標為-1 path[i]=-1; } } //先把起始頂點加入s s[x]=1; for(int i=0;i<length;i++) { //首先需要尋找start頂點到各頂點最短的路徑 int min=Integer.MAX_VALUE; int v=0; //記錄x到各頂點最短的 for(int j=0;j<length;j++) { if(s[j]!=1&&x!=j&&distance[x][j]!=0&&distance[x][j]<min) { min=distance[x][j]; v=j; } } //v 是目前x到各頂點最短的 s[v]=1; //修正最短路徑distance及最短距離path for(int j=0;j<length;j++) { if(s[j]!=1&&distance[v][j]!=0&&(min+distance[v][j]<distance[x][j]||distance[x][j]==0)) { //說明加入了中間頂點之後找到了更短的路徑 distance[x][j]=min+distance[v][j]; path[j]=v; } } } //列印最短路徑值 Stack <Integer>stack=new Stack<Integer>(); for(int i=0;i<length;i++) { if(distance[x][i]!=0) { System.out.println(mapping[x]+"-->"+mapping[i]+" 最短路徑長度:"+distance[x][i]); //path儲存路徑,可以逆序輸出,可以藉助棧實現正序輸出 System.out.print("逆序最短路徑輸出:"); int index=i; while(index!=-1) { System.out.print(mapping[index]+" "); stack.push(mapping[index]); index=path[index]; } System.out.print("正序最短路徑輸出:"); while(!stack.isEmpty()) { System.out.print(stack.pop()+" "); } System.out.println(); } } } public static void main(String[] args) { int[] vetexes={1,2,3,4,5,6}; Dijkstra graph=new Dijkstra(vetexes); graph.addEdge(1, 2,16);graph.addEdge(2, 1,16); graph.addEdge(1, 3,1);graph.addEdge(3, 1,1); graph.addEdge(1, 5,12);graph.addEdge(5, 1,12); graph.addEdge(1, 6,15);graph.addEdge(6, 1,15); graph.addEdge(2, 4,2);graph.addEdge(4, 2,2); graph.addEdge(2, 6,8);graph.addEdge(6, 2,8); graph.addEdge(3, 5,5);graph.addEdge(5, 3,5); graph.addEdge(4, 6,3);graph.addEdge(6, 4,3); graph.addEdge(5, 6,8);graph.addEdge(6, 5,8); graph.addEdge(4, 5,9);graph.addEdge(5, 4,9); graph.dijkstra(1); } }