Dijkstra算法求单源最短路径Java实现

如果所采用的实现方式合适,Dijkstra算法的运行时间要低于前面所说的Bellman_Ford算法,但是Dijkstra算法要求图中没有负边。Dijkstra算法在运行过程中维持的关键信息是一组结点集合S。从源结点s到该集合中每个结点之间的最短路径已经被找到。算法重复从结点集V-S中选择最短路径估计最小的结点u,将u加入到集合S,然后对所有从u发出的边进行松弛(有关松弛操作可见http://blog.csdn.net/john_bian/article/details/74612722)。下面是《算法导论》书中所给的伪代码:

Dijkstra算法求单源最短路径Java实现_第1张图片

在这个实现方式中,我们使用了一个最小优先队列Q来保存结点集合,每个结点的关键值为其d值。下面则是运用Dijkstra算法求解单源最短路径的过程的一个例子。

Dijkstra算法求单源最短路径Java实现_第2张图片

以下是用Java代码的具体实现

package test7;

/**
 * 边
 * @author sdu20
 *
 */
public class Edge {
	
	private int v1;
	private int v2;
	private int weight;
	
	public Edge(int v1,int v2,int weight){
		this.v1 = v1;
		this.v2 = v2;
		this.weight = weight;
	}
	
	public boolean equals(Edge edge){
		return this.v1==edge.getV1() && this.v2==edge.getV2() &&this.weight == edge.getWeight();
	}
	
	public int getV1(){
		return v1;
	}
	
	public int getV2(){
		return v2;
	}
	
	public int getWeight(){
		return weight;
	}
	
	public String toString(){
		String str = "[ "+v1+" , "+v2+" , "+weight+" ]";
		return str;
	}

}

package test7;

import java.util.*;

/**
 * Dijkstra算法求解单源最短路径
 * @author sdu20
 *
 */

public class Graph {

	private LinkedList[] edgeLinks;
	private int vNum;	//顶点数
	private int edgeNum;	//边数
	private int[] distance;	//存放v.d
	private int[] prenode;	//存放前驱节点
	private LinkedList S;	//已经求到最短路径的顶点集合
	private LinkedList Q;	//尚未求到最短路径的顶点集合
	public static final int INF = 10000;	//无穷大
	public static final int NIL = -1;	//表示不存在
	
	public Graph(int vnum){
		this.vNum = vnum;
		edgeLinks = new LinkedList[vnum];
		edgeNum = 0;
		distance = new int[vnum];
		prenode = new int[vnum];
		for(int i = 0;i();
	}
	
	public void insertEdge(Edge edge){		
		int v1 = edge.getV1();
		edgeLinks[v1].add(edge);
		edgeNum++;		
	}
	
	public void bianli(){
		System.out.println("共有 "+vNum+" 个顶点, "+edgeNum+" 条边");
		for(int i = 0;i list = (LinkedList) edgeLinks[i].clone();
			while(!list.isEmpty()){
				Edge edge = list.pop();
				System.out.println(edge.toString());
			}
		}
	}
	
	/**
	 * 对最短路径估计和前驱节点进行初始化
	 * @param start
	 */
	public void INITIALIZE_SINGLE_SOURCE(int start){
		for(int i = 0;idistance[v1]+w){
			distance[v2] = distance[v1]+w;
			prenode[v2] = v1;
		}
	}
	
	/**
	 * Dijkstra算法实现
	 * @param start
	 */
	public void DIJKSTRA(int start){
		
		INITIALIZE_SINGLE_SOURCE(start);
		
		S = new LinkedList<>();
		Q = new LinkedList<>();
		for(int i = 0;i list = (LinkedList) edgeLinks[u].clone();
			while(!list.isEmpty()){
				Edge edge = list.pop();
				RELAX(edge);
			}
		}
		
		ShowResult();
	
	}
	
	private int EXTRACT_MIN(LinkedList q){
		
		if(q.isEmpty())
			return -1;
		
		int min = q.getFirst();
		for(int i = 0;idistance[v]){
				min = v;
			}
		}
		int min2 = min;
		q.remove(q.indexOf(min));
		return min;
	}
	
	private void ShowResult(){
		System.out.println("=========Result==========");
		Stack[] routes = new Stack[vNum];
		for(int i = 0;i();
			int j = i;
			while(j != NIL){
				routes[i].push(j);
				j = prenode[j];
			}
			
			System.out.print(i+"("+distance[i]+") : ");
			while(!routes[i].isEmpty()){
				int k = routes[i].pop();
				System.out.print("-->"+k);
			}
			System.out.println();
		}	
	}
}

package test7;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		bookGraph();
	}
	
	private static void bookGraph(){
		Graph graph = new Graph(5);
		Edge[] edges = new Edge[10];
		
		edges[0] = new Edge(0,1,10);
		edges[1] = new Edge(0,3,5);
		edges[2] = new Edge(1,2,1);
		edges[3] = new Edge(1,3,2);
		edges[4] = new Edge(2,4,4);
		edges[5] = new Edge(3,1,3);
		edges[6] = new Edge(3,2,9);
		edges[7] = new Edge(3,4,2);
		edges[8] = new Edge(4,0,7);
		edges[9] = new Edge(4,2,6);
		
		for(int i = 0;i<10;i++)
			graph.insertEdge(edges[i]);
		
		graph.bianli();
		graph.DIJKSTRA(0);
	}

}

运行截图如下所示

Dijkstra算法求单源最短路径Java实现_第3张图片

你可能感兴趣的:(Java,算法导论)