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

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

算法导论——最短路径Dijkstra算法的相关文章

有向网络(带权的有向图)的最短路径Dijkstra算法

什么是最短路径? 单源最短路径(所谓单源最短路径就是只指定一个顶点,最短路径是指其他顶点和这个顶点之间的路径的权值的最小值) 什么是最短路径问题? 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. 什么是Dijkstra算法? 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,

数据结构:单源最短路径--Dijkstra算法

Dijkstra算法 单源最短路径 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. Dijkstra算法 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,E>,令S为已确定了最短路径顶点的集合,则可用V-S表示剩余未确定最短路径顶点的集合.假设V0是源点,则初始 S={V

数据结构与算法——最短路径Dijkstra算法的C++实现

之前的讨论了无权图的最短路径算法.数据结构与算法--无权最短路径算法的C++实现 如果是加权图,那么问题就变得困难了,不过仍然可以采用无权情况的想法. 我们仍然保留之前的信息.因此,每个顶点会被标记为known或unknown,每个顶点保留一个尝试性的距离dv(这个距离是只使用一些known顶点作为中间顶点从s到v的最短路径的长),每个顶点还保留字段pv,该字段是记录引起dv变化的最后的顶点. 图顶点信息的数据结构: //保存每个顶点信息的数据结构 struct GraphNode{ bool

最短路径算法之二——Dijkstra算法

Dijkstra算法 Dijkstra算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 注意该算法要求图中不存在负权边. 首先我们来定义一个二维数组Edge[MAXN][MAXN]来存储图的信息. 这个图的Edge数组初始化以后为 我们还需要用一个一维数组dis来存储1号顶点到其余各个顶点的初始路程,如下. 这个dis数组中存的是最短路的估计值. 通过Dijkstra算法来松弛后,dis存的为从初始点到各点的精确值(最短路径)了. Dijkstra算法实现如下(以HDU1548为例

最短路径-Dijkstra算法与Floyd算法

一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1    ADE:2   ADCE:3   ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径. AE:100   ADE:90   ADCE:60   ABCE:70 ③单源点最短路径问题 问题描述:给定带权有向图G=(V, E)和源点v∈V,求从v到G中其余各顶点的最短路径. 应用实例--计算机网络传输的问题:怎样找到一种最经济的方式,从一台计算机向网上所有其它计算机发送一条消息. ④每

单源最短路径Dijkstra算法

1.单源最短路径 函数:返回还未被收录顶点中dist最小者 1 Vertex FindMinDist(MGraph Graph, int dist[], int collected[]) 2 { 3 /*返回未被收录顶点中dist最小者*/ 4 Vertex MinV, V; 5 int MinDist = INFINITY; 6 7 8 for (V = 0; V < Graph->Nv; ++V) 9 { 10 if (collected[V] == false && di

有向图中单个源点到终点的最短路径--Dijkstra算法与实现

1.Dijkstra算法能够解决有向图中单个源点到另一终点的最短路径问题,它的算法过程如下: 1)用矩阵graph[]N[N](N为图中节点个数)表示带权的有向图G.若图中两个节点vi和vj是连通的,则graph[i][j]表示这两个节点之间边的权值:若两节点vi和vj不是连通的,则graph[i][j] = -1. 2)设S为从某点start_vec开始的最短路径path的终点集合,初始状态时,集合S中只有起始节点start_vec.设从起始节点start_vec到其余节点vi的最短路径长度为

单源最短路径 dijkstra算法实现

本文记录一下dijkstra算法的实现,图用邻接矩阵表示,假设图为无向图,并且连通,有向图,不连通图的做法类似. 算法简述: 首先确定"单源"的源,假设是第0个顶点. 维护三个数组dist[], color[], path[],设其下标分别为0-i-n-1: dist[] 表示源点到顶点i的最短距离,在初始化时,如果源点到顶点i有路径,则初始化为路径的权重,否则初始化为INT_MAX: color[] 数组其实表示两个集合,即color[i]值为1的集合表示已经确定最短路径的点的集合,

最短路径-Dijkstra算法(转载)

注意:以下代码 只是描述思路,没有测试过!! Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边. 问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到