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->
时间: 2024-10-13 02:18:44