zoukankan      html  css  js  c++  java
  • 最短路径BellmanFord , Dijsktra

     最短路径算法也是常用的图算法,在网上看到了一份c的代码,写的很清楚,今天有空给写成java的了,就当练手了。另,算法导论362页详细介绍了Bellman-Ford算法,本来打算再写个Dijsktra算法的,可是今天比较赖,就写这一个算法吧。

    package path;
    import java.util.HashSet;
    
    public class BellmanFord {	
    
    	private int MAX = Integer.MAX_VALUE;
    	private int  N  = 1024;
    	//顶点数 , 边数 , 起点
    	private int nodenum, edgenum, original;
    	//图的边
    	private Edge [] edge = new Edge[N];
    	//保存距离
    	private double [] dis = new double[N];
    	private int [] pre = new int[N];
    	/**
    	 * @function 
    	 * @return
    	 */
    	boolean calculate()
    	{
    		for(int i = 1; i <= nodenum; ++i) //初始化
    			dis[i] = (i == original ? 0 : MAX);
    		for(int i = 1; i <= nodenum - 1; ++i)
    			for(int j = 1; j <= edgenum; ++j)
    				//松弛
    				if(dis[edge[j].v] > dis[edge[j].u] + edge[j].cost){
    					dis[edge[j].v] = dis[edge[j].u] + edge[j].cost;
    					pre[edge[j].v] = edge[j].u;
    				}
    				boolean flag = true; 
    				//判断是否含有负权回路
    				for(int i = 1; i <= edgenum; ++i)
    					if(dis[edge[i].v] > dis[edge[i].u] + edge[i].cost){
    						flag = false;
    						break;
    					}
    					return flag;
    	}
    
    	void print_path(int root) //打印最短路的路径(反向)
    	{
    		while(root != pre[root]){ //前驱
    			System.out.print(root + "-->");
    			root = pre[root];
    		}
    		if(root == pre[root])
    			System.out.print(root + "
    ");
    	}
    
    	public boolean init(Edge [] edges){
    		try{
    			nodenum = edgenum = 0;
    			HashSet<Integer> vSet = new HashSet<Integer>();
    			for(int i = 1 ; i < edges.length ; ++i){
    				edgenum++;
    				edge[i] = edges[i];
    				vSet.add(edges[i].u);
    				vSet.add(edges[i].v);
    			}
    			nodenum = vSet.size();
    			return true;
    		}catch(Exception e){
    			e.printStackTrace();
    			return false;
    		}
    	}
    	private void calcShortestPath(int original){
    		this.original = original;
    		pre[original] = original;
    		if(calculate())
    			for(int i = 1; i <= nodenum; ++i){ //每个点最短路
    				System.out.print(dis[i] + "
    ");
    				System.out.print("Path:");
    				print_path(i);
    			}
    		else
    			System.out.println("have negative circle
    ");
    
    	}
        public static void main(String [] args)
    	{
        	BellmanFord bellman = new BellmanFord();
        	
        	Edge [] edges = new Edge [7];
        	edges[1] = new Edge(1 , 2 , 2);
        	edges[2] = new Edge(1 , 3 , 5);
        	edges[3] = new Edge(4 , 1 , 10);
        	edges[4] = new Edge(2 , 4 , 4);
        	edges[5] = new Edge(4 , 2 , 4);	
        	edges[6] = new Edge(3 , 4 , 2);	
        	
        	bellman.init(edges);
        	bellman.calcShortestPath(1);
    	}
        
    	
    }
    
    class Edge //边
    {	// u为边的前驱结点,v为后继结点(暂且用前驱、后继来说)
    	int u, v;
    	//边的权重
    	double cost;
    	public Edge(int u , int v , double cost){
    		this.u = u;
    		this.v = v;
    		this.cost = cost;
    	}
    }
    

      

  • 相关阅读:
    C语言的选择结构和条件判断
    学习C语言必须知道的理论知识(第三章数据类型的分类)
    基本输入输出函数以及其格式.
    学习C语言必须知道的理论知识(第三章常量和变量)
    简单的算术题。
    学习C语言必须知道的理论知识(第二章算法)
    学习C语言必须知道的理论知识(第一章)
    学习C语言必须知道的理论知识(第三章常量类型,运算符和表达式)
    C语言中的循环控制语句.
    彻底弄懂JS中的this
  • 原文地址:https://www.cnblogs.com/nocml/p/3649325.html
Copyright © 2011-2022 走看看