稀疏图Johnson算法

在前面的文章《所有节点对的最短路径问题》中,我们介绍了用于稀疏图的Johnson算法,由于代码比较长,我们将其单独放在一篇文章之中。

Johnson算法的时间复杂度在使用二叉堆作为最小优先队列的情况下为O((V^2 + EV)lgV);在使用斐波那契堆作为最小优先队列的时候为O(V^2lgV + VE),因此尤其是在稀疏图的情况下,其效率要比Floyd-Warshall高。

下面给出Java实现的代码:

import java.util.*;
public class Johnson{
	static final int MAX = 20;  //最大点数
	static int[][] g;
	static int[] h = new int[MAX];
//	static LinkedList S = new LinkedList();  
	static PriorityQueue Q = new PriorityQueue(); //Q = V-S  
	static ArrayList nodes = new ArrayList();
	static int[][] D;
	
	static int ver;  //节点数
    	static int edge; //边数
    	static final int BELLMAN_FORD = 1;
    	static final int DIJKSTRA = 2;
    	/************全局数据结构****************/
	static class Elem implements Comparable  
	{  
		public int s; //节点编号 
		public int d;  //与源节点距离
		public Elem(int s,int d){  
		    	this.s = s;  
		    	this.d = d;  
		}
		public int compareTo(Elem e){return d - e.d;}  
	}
	/***********以下是Johnson算法实现*******************/
	static void johnson(){
		
		int s = ver; //新添加一个节点
		int[][] g_new = new int[ver+1][ver+1];
		for(int u = 0;u < g_new.length;u++){
			for(int v = 0;v < g_new.length;v++){
				if(v == g.length){g_new[u][v] = Integer.MAX_VALUE;continue;}
				if(u == g.length){g_new[u][v] = 0; continue;}
				g_new[u][v] = g[u][v];
			}
		}
		
		if(bellman_ford(g_new,s) == false) {System.out.println("circle exist");return;}
		
		for(Elem e:nodes) h[e.s] = e.d;
		System.out.println("h[v]: from 0 to n");
		for(int i = 0;i nodes.get(u).d + g[u][v]) return false;
			}
		}    
		return true;    
	}
    	/************以下是Dijkstra实现*************/
	
	static void dijkstra(int[][] g,int source){  
		init(g,source,DIJKSTRA);
		while(Q.size() > 0){  
		    Elem u = Q.poll();  
//		    S.add(u);  
		    for(int v = 0;v < g.length;v++){  
			if(g[u.s][v] != Integer.MAX_VALUE && nodes.get(v).d > u.d + g[u.s][v]){  
			    Elem nv = nodes.get(v);  
			    //下面删除后添加是为了使PriorityQueue能够重新调整  
			    Q.remove(nv);  
			    nv.d = u.d + g[u.s][v];  
			    Q.offer(nv);  
			}  
		    }  
		}
	}
	/**************用于获取输入数据,初始化图G的***************/
	static void input(){  
		Scanner cin = new Scanner(System.in);  
		System.out.println("请输入 点数 边数");  
		ver = cin.nextInt();  
		edge = cin.nextInt();  
		g  = new int[ver][ver];
		D = new int[ver+1][ver+1];
		int s,e,w;
		for(int i = 0;i < ver;i++){
			for(int j = 0;j < ver;j++) {g[i][j] = Integer.MAX_VALUE;}
		}
		System.out.println("起点 终点 权值");  
		for(int i=0;i
运行如下:

请输入 点数 边数
5 6
起点 终点 权值
0 1 -3
0 3 -5
0 2 4
3 2 2
3 4 3
4 1 -3

运行结果如下:

h[v]: from 0 to n
0     -5     -3     -5     -2     
G' :
inf    2    7    0    inf    
inf    inf    inf    inf    inf    
inf    inf    inf    inf    inf    
inf    inf    0    inf    0    
inf    0    inf    inf    inf    
D[i][j]: shortest path from i to j
0    -5    -3    -5    -2    
inf    0    inf    inf    inf    
inf    inf    0    inf    inf    
inf    0    2    0    3    
inf    -3    inf    inf    0   


你可能感兴趣的:(算法与数据结构)