zoukankan      html  css  js  c++  java
  • Dijkstra 算法

     今天又翻了翻算法导论,看了看dijstra算法。兴趣来了就实现了下。完全按照书上的步骤实现,没有使用最小堆等数据结构,使用的邻接表方式表示图。因此实现的算法效率很抵,不过这里只是想通过程序来说明这个算法。不是工程上用的。如果工程上使用,最好用矩阵表示图,然后再使用最小堆。。。。不多说了,直接上代码。

    (原理参见算法导论第二版p366)

    package Graph;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Stack;
    
    
    public class Dijkstra2 {
    	private AdjacencyList adjList = new AdjacencyList();
    	public static void main(String[] args) {
    		try{
    			double[][] matrix = { 
    					{ util.max, 5, util.max, util.max, 10 }, 
    					{ util.max, util.max, 2, 9, 3 },
    					{ 7, util.max, util.max, 6, util.max },
    					{ util.max, util.max, 4 , util.max, util.max },
    					{ util.max, 2, util.max, 1, util.max } 
    					};
    			
    			Dijkstra2 dijkstra = new Dijkstra2(matrix);
    			
    			dijkstra.adjList.print();
    			dijkstra.calculate(0);
    			dijkstra.print();
    			
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    	}
    	
       public Dijkstra2(double [][] matrix){
    	   adjList = new AdjacencyList(matrix);
       }
       //存储前驱节点
       private int [] pre ;
       //存储距离
       private double [] dist;
       /**
        * @function 计算最近路径
        * @param v 源点
        */
       public void calculate(int v){
    	   pre = new int [this.adjList.size()];
    	   dist = new double[this.adjList.size()];
    	   //s序列,存放
    	   boolean [] s = new boolean [this.adjList.size()];
    	   
    	   //初始化距离
    	   Arrays.fill(dist, util.max);
    	   //初始化前驱节点
    	   Arrays.fill(pre, -1);
    	   //初始队列s中没有点
    	   Arrays.fill(s, false);
    	   
    	   //源点的距离为0
    	   dist[v] = 0;
    	   int gray = v;
    	  
    	   while(true){
    		   //找出距离最小的点
    		   double mindis = Double.MAX_VALUE;
    		   for(int i = 0 ; i < dist.length ; i++){
    			   if(mindis > dist[i] && !s[i]){
    				   mindis = dist[i];
    				   gray = i;
    			   }
    		   }
    		   //把找到的这个点加入到s队列中
    		   s[gray] = true;
    		   
    		   //======对与gray点有边的点进行松驰=====
    		   Node pnode = adjList.get(gray);
    		   //向后移一个节点,因为第一个节点是自己。后面的点才是当前节点的后继节点。
    		   pnode = pnode.next;
    		   while(pnode != null){
    			   //后继节点与当前节点的距离 + 当前节点与源点的距离   < 	后继节点到源点的距离
    			   if(pnode.weight + mindis < dist[pnode.index]){
    				   //后继节点的到源点的距离 更新 为 后继节点与当前节点的距离 + 当前节点与源点的距离
    				   dist[pnode.index] = pnode.weight + mindis;
    				   //后继节点的前驱节点更新为 当前节点
    				   pre[pnode.index] = adjList.get(gray).index;
    			   }
    			   //下一个后继节点
    			   pnode = pnode.next;
    		   }
    		   
    		   //===判断s中是否包含全部的点了
    		   boolean con = false;
    		   for(boolean b : s)
    			   if(b == false){
    				   con = true;
    				   break;
    			   }
    		   if(!con)
    			   break;
    		   
    	   }
    	   
       }
    	
     
    	public void print() {
    		for(int i = 0 ; i < dist.length ; i++){
    			System.out.print(dist[i] + "	");
    			printpath(i);
    			System.out.println();
    		}
    	}
    
    	public void printpath(int v){
    		Stack<Integer> stack = new Stack<Integer>(); 
    		while(pre[v] >= 0){
    			stack.add(pre[v]);
    			v = pre[v];
    		}
    		while(stack.size() > 0)
    			System.out.print(stack.pop() + "	");
    	}
       public double getWeight(Node node , int index){
    	   while(node != null){
    		   int ndx = node.index;
    		   if(ndx == index)
    			   return node.weight;
    		   node = node.next;
    	   }
    	   return util.max;
       }
    }
    
    class AdjacencyList{
    	
    	private List<Node> adjList = new ArrayList<Node>();
    	public AdjacencyList(){};
    	
    	public int size(){
    		return adjList.size();
    	}
    	public Node get(int index){
    		return this.adjList.get(index);
    	}
    	public List<Node> getData(){
    		return this.adjList;
    	}
    	public AdjacencyList(double [][] matrix){
    		for(int i = 0 ; i < matrix.length ; i++){
    			double [] vals = matrix[i];
    			addData(i , vals);
    		}
    	}
    	
    	public void addData(int v , double [] vals){
    		Node  node = new Node(v , 0);
    		Node head = node;
    		for(int j = 0 ; j < vals.length ; j++){
    			if(vals[j] < util.max && vals[j] != 0.0){
    				node.next = new Node();
    				node = node.next;
    				node.set( j , vals[j]);
    			}
    		}
    		adjList.add(head);
    	}
    	
    	public void print(){
    		for(Node node : adjList){
    			while(node != null){
    				System.out.print(node.toString() + "	");
    				node = node.next;
    			}
    			System.out.println();
    		}
    	}
    }
    
    
    class Node{
    	Node next;
    	double weight = util.max;
    	int index = -1;
    	public Node(){
    		
    	}
    	
    	public Node(int index , double weight){
    		set(index , weight);
    	}
    	public void set(int index , double weight){
    		this.index = index;
    		this.weight = weight;
    	}
    	@Override
    	public String toString() {
    		// TODO Auto-generated method stub
    		return "[ " + index + " , " + weight + " ]"; 
    	}
    }
    
    class util{
    	public static double max = Double.MAX_VALUE;
    }
    

      

  • 相关阅读:
    Step by step Dynamics CRM 2013安装
    SQL Server 2012 Managed Service Account
    Step by step SQL Server 2012的安装
    Step by step 活动目录中添加一个子域
    Step by step 如何创建一个新森林
    向活动目录中添加一个子域
    活动目录的信任关系
    RAID 概述
    DNS 正向查找与反向查找
    Microsoft Dynamics CRM 2013 and 2011 Update Rollups and Service Packs
  • 原文地址:https://www.cnblogs.com/nocml/p/3634583.html
Copyright © 2011-2022 走看看