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

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


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


以下是用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<Edge>[] edgeLinks;
	private int vNum;	//顶点数
	private int edgeNum;	//边数
	private int[] distance;	//存放v.d
	private int[] prenode;	//存放前驱节点
	private LinkedList<Integer> S;	//已经求到最短路径的顶点集合
	private LinkedList<Integer> 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<vnum;i++)
			edgeLinks[i] = new LinkedList<>();
	}
	
	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<vNum;i++){
			LinkedList<Edge> list = (LinkedList<Edge>) 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;i<vNum;i++){
			distance[i] = INF;
			prenode[i] = NIL;
		}
		distance[start] = 0;
	}
	
	/**
	 * 松弛
	 * @param edge
	 */
	public void RELAX(Edge edge){
		int v1 = edge.getV1();
		int v2 = edge.getV2();
		int w = edge.getWeight();
		if(distance[v2]>distance[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<vNum;i++){
			Q.add(i);
		}
		
		while(!Q.isEmpty()){
			int u = EXTRACT_MIN(Q);
			S.add(u);
			LinkedList<Edge> list = (LinkedList<Edge>) edgeLinks[u].clone();
			while(!list.isEmpty()){
				Edge edge = list.pop();
				RELAX(edge);
			}
		}
		
		ShowResult();
	
	}
	
	private int EXTRACT_MIN(LinkedList<Integer> q){
		
		if(q.isEmpty())
			return -1;
		
		int min = q.getFirst();
		for(int i = 0;i<q.size();i++){
			int v = q.get(i);
			if(distance[min]>distance[v]){
				min = v;
			}
		}
		int min2 = min;
		q.remove(q.indexOf(min));
		return min;
	}
	
	private void ShowResult(){
		System.out.println("=========Result==========");
		Stack<Integer>[] routes = new Stack[vNum];
		for(int i = 0;i<vNum;i++){
			routes[i] = new Stack<>();
			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);
	}

}

运行截图如下所示


  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值