码迷,mamicode.com
首页 > 编程语言 > 详细

算法导论——最短路径Dijkstra算法

时间:2015-05-27 23:06:01      阅读:433      评论:0      收藏:0      [点我收藏+]

标签:

package org.loda.graph;

import org.loda.structure.IndexMinQ;
import org.loda.structure.Stack;
import org.loda.util.In;

/**
 * 
 * @ClassName: Dijkstra
 * @Description: Dijkstra最短路径算法--贪心算法
 * @author minjun
 * @date 2015年5月27日 下午4:49:27
 * 
 */
public class Dijkstra {

	/**
	 * 最短路径上的前面一个节点
	 */
	private int[] prev;

	/**
	 * 距离远点的距离
	 */
	private double[] dist;

	/**
	 * 利用带索引的优先队列来实现根据权重排序,以及根据索引i修改权重值
	 */
	private IndexMinQ<Double> q;
	
	/**
	 * 原点
	 */
	private int s;

	/**
	 * WeightDigraph g 加权有向图 int s 起始点
	 */
	public Dijkstra(WeightDigraph g, int s) {
		int v = g.v();
		this.s=s;

		prev = new int[v];

		dist = new double[v];

		for (int i = 0; i < v; i++) {
			// 设默认前一个节点为-1(这里表示为null)
			prev[i] = -1;
			// 设默认距离为不可达
			dist[i] = Integer.MAX_VALUE;
		}

		dist[s] = 0.0;

		q = new IndexMinQ<Double>(v);

		q.insert(s, dist[s]);

		while (!q.isEmpty()) {
			//利用贪心算法的思想,获取当前距离远点s最近的顶点,在这个顶点基础之上扩展与其他点的最近距离
			int i = q.delMin();

			//松弛这个顶点周围所有的边,直到s到达这些边另一端顶点的距离保持最小
			relax(i, g);

		}

	}

	private void relax(int i, WeightDigraph g) {
		for (Edge edge : g.adj(i)) {
			int j = edge.otherSide(i);

			// i->j
			
			//如果s->j的距离比s->i+weigth(i->j)更近,那么将s->j的距离dist和路径prev修改为更近的距离和更优的前置点
			if (dist[j] > dist[i] + edge.weight()) {
				dist[j] = dist[i] + edge.weight();
				prev[j] = i;
				
				//找到当前最优解后更新或者添加这个较优解到优先队列中
				if (q.contains(j))
					q.changeKey(j, dist[i]);
				else
					q.insert(j, dist[i]);
			}

		}
	}
	
	//原点->d的最短距离
	public double distTo(int d){
		return dist[d];
	}

	//原点->d的最短路径
	public Iterable<Integer> pathTo(int i){
		if(dist[i]==Integer.MAX_VALUE)
			throw new RuntimeException("无法从原点"+s+"到达目标点"+i);
		
		Stack<Integer> reverse=new Stack<Integer>();
		
		for(int v=i;v!=-1;v=prev[v]){
			reverse.push(v);
		}
		
		return reverse;
	}
	
	public static void main(String[] args) {
		WeightDigraph g=new WeightDigraph(new In("F:\\算法\\attach\\tinyEWD.txt"));
		Dijkstra d=new Dijkstra(g, 0);
		
		for(int i=0;i<g.v();i++){
			System.out.println("从原点"+d.s+"到"+i+"的最短距离为:"+d.distTo(i));
			System.out.print("路径为:");
			for(int j:d.pathTo(i)){
				System.out.print(j+"->");
			}
			System.out.println();
		}
	}
}

数据结构有向权重图:

package org.loda.graph;

import org.loda.structure.Bag;
import org.loda.structure.Queue;
import org.loda.util.In;

/**
 * 
 * @ClassName: WeightDigraph
 * @Description: 带权重的有向图
 * @author minjun
 * @date 2015年5月27日 下午4:34:00
 * 
 */
public class WeightDigraph {

	private Bag<Edge>[] bags;

	private int v;

	private int e;

	private Queue<Edge> edges;

	@SuppressWarnings("unchecked")
	public WeightDigraph(int v) {
		this.v = v;
		bags = new Bag[v];
		edges = new Queue<Edge>();

		for (int i = 0; i < v; i++) {
			bags[i] = new Bag<Edge>();
		}
	}

	public WeightDigraph(In in) {
		this(in.readInt());
		int m = in.readInt();
		for (int i = 0; i < m; i++) {
			add(in.readInt(), in.readInt(), in.readDouble());
		}
	}

	public void add(int a, int b, double weight) {
		Edge edge = new Edge(a, b, weight);

		bags[a].add(edge);

		edges.enqueue(edge);

		e++;

	}

	public Iterable<Edge> adj(int a) {
		return bags[a];
	}

	public Iterable<Edge> edges() {
		return edges;
	}

	public int v() {
		return v;
	}

	public int e() {
		return e;
	}
}



文本内容:

8
15
4 5 0.35
5 4 0.35
4 7 0.37
5 7 0.28
7 5 0.28
5 1 0.32
0 4 0.38
0 2 0.26
7 3 0.39
1 3 0.29
2 7 0.34
6 2 0.40
3 6 0.52
6 0 0.58
6 4 0.93

输出结果:

从原点0到0的最短距离为:0.0
路径为:0->
从原点0到1的最短距离为:1.05
路径为:0->4->5->1->
从原点0到2的最短距离为:0.26
路径为:0->2->
从原点0到3的最短距离为:0.9900000000000001
路径为:0->2->7->3->
从原点0到4的最短距离为:0.38
路径为:0->4->
从原点0到5的最短距离为:0.73
路径为:0->4->5->
从原点0到6的最短距离为:1.5100000000000002
路径为:0->2->7->3->6->
从原点0到7的最短距离为:0.6000000000000001
路径为:0->2->7->




算法导论——最短路径Dijkstra算法

标签:

原文地址:http://my.oschina.net/u/1378920/blog/420762

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!