1. 程式人生 > >鄰接矩陣的dijkstra演算法 迭代法以及使用PriorityQueue的java實現

鄰接矩陣的dijkstra演算法 迭代法以及使用PriorityQueue的java實現

import java.util.PriorityQueue;

public class DijkstraMy {
	   //設定最大值
	   int MAX=999;
	   //頂點總個數
       int total;
       //鄰接矩陣表示距離
       int[][] matrix;
       //結點相關資訊
       String[] nodes;
       //儲存最後結果
       int[] dis;
       //標記結點
       int[] mark;
       DijkstraMy(int total,String[] nodes)
       {
    	   this.total = total;  
           this.nodes = nodes;  
           this.matrix = new int[total][total];  
           this.dis = new int[total];  
           this.mark = new int[total];  
       }
       private void initMatrix() {  
           // 初始化矩陣為最大值(各節點都不連通)  
           for (int i = 0; i < this.total; i++) {  
               for (int j = 0; j < this.total; j++) {  
                   if (i == j) {  
                       this.matrix[i][j] = 0;  
                   } else {  
                       this.matrix[i][j] = MAX;  
                   }  
               }  
           }  
     
           // 手動設定有向路徑  
           // A->B, A->E, A->D  
           this.matrix[0][1] = 2;  
           this.matrix[0][4] = 3;  
           this.matrix[0][3] = 1;  
           // B->C  
           this.matrix[1][2] = 2;  
           // C->F  
           this.matrix[2][5] = 1;  
           // D->E, D->G  
           this.matrix[3][4] = 5;  
           this.matrix[3][6] = 2;  
           // E->F, E->H  
           this.matrix[4][5] = 6;  
           this.matrix[4][7] = 1;  
           // F->I  
           this.matrix[5][8] = 3;  
           // G->H  
           this.matrix[6][7] = 4;  
           // H->F, H->I  
           this.matrix[7][5] = 1;  
           this.matrix[7][8] = 2;  
       }  
       
       private void printMatrix() {  
           System.out.println("--------- weighted directed matrix ---------");  
           System.out.println("---0---1---2---3---4---5---6---7---8---");  
           System.out.println("---A---B---C---D---E---F---G---H---I---");  
           for (int i = 0; i < this.total; i++) {  
               System.out.print("-" + this.nodes[i] + "|");  
               for (int j = 0; j < this.total; j++) {  
                   System.out.print(String.format("%03d", this.matrix[i][j]) + "-");  
               }  
               System.out.print("\n");  
           }  
           System.out.println("--------- weighted directed matrix ---------");  
       } 
       
      private void dijkstra1(int s)
      {
    	  for(int i=0;i<total;i++ )
    		  mark[i]=0;
    	  mark[s]=1;
    	  for(int i=0;i<total;i++)
    	  {
    		  dis[i]=matrix[s][i];
    	  }
    	  /**每次找到一個最小值,標記,然後修改其相鄰的值*/
    	  for(int i=0;i<total;i++)
    	  {
    		  int min=MAX;
    		  int index=-1;
    		  for(int j=0;j<total;j++)
    		  {
    			  if(mark[j]==0&&dis[j]<min)
    			  {
    				  index=j;
    				  min=matrix[s][j];
    			  }
    		  }
    		  if(index==-1) return;
    		  mark[index]=1;
    		  for(int k=0;k<total;k++)
    		  {
    			  if(mark[k]==0&&dis[index]+matrix[index][k]<dis[k])
    			  {
    				  dis[k]=dis[index]+matrix[index][k];
    			  }
    		  }
    		  printDis(0,this.nodes[i],"第"+i+"次");
    	  }
      }
      //使用小頂堆,幫助找到最小值
      private void dijkstra2()
      {
    	  class Node implements Comparable<Node>
    	  {
    		  int id;
    		  int weight;
    		  Node(int i,int j)
    		  {
    			  this.id=i;
    			  this.weight=j;
    		  }
			@Override
			public int compareTo(Node node) {
				if(this.weight==node.weight)
					return 0;
				else if(this.weight<node.weight)
					return -1;
				else
					return 1;
			}
    	  }
    	  //小頂堆
    	  PriorityQueue<Node> queue=new PriorityQueue<Node>();
    	  queue.offer(new Node(0,0));
    	  for(int i=0;i<total;i++ )
    		  mark[i]=0;
    	  for(int i=0;i<total;i++)
    	  {
    		  dis[i]=matrix[0][i];
    		  if(dis[i]!=MAX)
    		  queue.offer(new Node(i,dis[i]));
    	  }
    	  int count=0;
    	  while(queue!=null)
    	  {
    		  count++;
    		 Node node=queue.poll();
    		 if(node==null) return;
    		 int index=node.id;
    		 mark[index]=1;	 
    		 for(int i=0;i<total;i++)
    		 {
    			 if(mark[i]==0&&dis[index]+matrix[index][i]<dis[i])
    			 {
    				dis[i]=dis[index]+matrix[index][i];
    				queue.add(new Node(i,dis[i]));
    			 }
    			 
    		 }
    		 printDis(0,"0","第"+count+"次"); 
    	  }
      }
      private void printDis(int i, String node, String pre) {  
          /*System.out.print("\n" + pre + "," + node + "," + i + "--->");  
          for (int t = 0; t < this.dis.length; t++) {  
              System.out.print(t + ",");  
          }*/ 
          System.out.print("\n" + pre + i + "--->");  
          for (int t : this.dis) {  
              System.out.print(t + ",");  
          }  
          System.out.print("\n");  
      }  
      public static void main(String[] args) {  
          String[] nodes = new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" };  
          DijkstraMy dij = new DijkstraMy(nodes.length, nodes);  
          dij.initMatrix();  
          dij.printMatrix();  
    
          System.out.println();  
          System.out.println("------ Dijkstra演算法-(迪傑斯特拉)演算法之迭代開始 ------");  
          dij.dijkstra1(0);  
          dij.printDis(0, "迭代結果", "最終值");  
          System.out.print("\n");  
          System.out.println("------ Dijkstra演算法-(迪傑斯特拉)演算法之迭代結束 ------");  
    
          System.out.println();  
          System.out.println("------ Dijkstra演算法-(迪傑斯特拉)演算法之優先佇列開始 ------");  
          dij.dijkstra2();  
          dij.printDis(0, "優先順序佇列", "最終值");  
          System.out.print("\n");  
          System.out.println("------ Dijkstra演算法-(迪傑斯特拉)演算法之優先佇列結束 ------");  
      }  
}