基本思想

通过Dijkstra计算图G中的最短路径时,需要指定起点vs(即从顶点vs开始计算)。

此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点,而U则是记录还未求出最短路径的顶点(以及该顶点到起点vs的距离)。

初始时,S中只有起点vs;U中是除vs之外的顶点,并且U中顶点的路径是"起点vs到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。

操作步骤

(1) 初始时,S只包含起点vs;U包含除vs外的其他顶点,且U中顶点的距离为"起点vs到该顶点的距离"[例如,U中顶点v的距离为(vs,v)的长度,然后vs和v不相邻,则v的距离为∞]。

(2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。

(3) 更新U中各个顶点到起点vs的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(vs,v)的距离可能大于(vs,k)+(k,v)的距离。

(4) 重复步骤(2)和(3),直到遍历完所有顶点。

接下来做一个简单例子求解:

package com.darrenchan.graph;

import java.util.ArrayList;
import java.util.List; public class ShortestPathDijkstra {
/** 邻接矩阵 */
private int[][] matrix;
/** 表示正无穷 */
private int MAX_WEIGHT = Integer.MAX_VALUE;
/** 顶点集合 */
private String[] vertexes; /**
* 创建图
*/
private void createGraph(int index) {
matrix = new int[index][index];
vertexes = new String[index]; int[] v0 = { 0, 1, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
int[] v1 = { 1, 0, 3, 7, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
int[] v2 = { 5, 3, 0, MAX_WEIGHT, 1, 7, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
int[] v3 = { MAX_WEIGHT, 7, MAX_WEIGHT, 0, 2, MAX_WEIGHT, 3, MAX_WEIGHT, MAX_WEIGHT };
int[] v4 = { MAX_WEIGHT, 5, 1, 2, 0, 3, 6, 9, MAX_WEIGHT };
int[] v5 = { MAX_WEIGHT, MAX_WEIGHT, 7, MAX_WEIGHT, 3, 0, MAX_WEIGHT, 5, MAX_WEIGHT };
int[] v6 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 3, 6, MAX_WEIGHT, 0, 2, 7 };
int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 9, 5, 2, 0, 4 };
int[] v8 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 7, 4, 0 };
matrix[0] = v0;
matrix[1] = v1;
matrix[2] = v2;
matrix[3] = v3;
matrix[4] = v4;
matrix[5] = v5;
matrix[6] = v6;
matrix[7] = v7;
matrix[8] = v8; vertexes[0] = "v0";
vertexes[1] = "v1";
vertexes[2] = "v2";
vertexes[3] = "v3";
vertexes[4] = "v4";
vertexes[5] = "v5";
vertexes[6] = "v6";
vertexes[7] = "v7";
vertexes[8] = "v8";
} /**
* Dijkstra最短路径。
*
* vs -- 起始顶点(start vertex) 即,统计图中"顶点vs"到其它各个顶点的最短路径。
*/
public void dijkstra(int vs) {
// flag[i]=true表示"顶点vs"到"顶点i"的最短路径已成功获取
boolean[] flag = new boolean[vertexes.length];
// U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离),与 flag配合使用,flag[i] == true 表示U中i顶点已被移除
int[] U = new int[vertexes.length];
// 前驱顶点数组,即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。
int[] prev = new int[vertexes.length];
// S的作用是记录已求出最短路径的顶点
String[] S = new String[vertexes.length]; // 步骤一:初始时,S中只有起点vs;U中是除vs之外的顶点,并且U中顶点的路径是"起点vs到该顶点的路径"。
for (int i = 0; i < vertexes.length; i++) {
flag[i] = false; // 顶点i的最短路径还没获取到。
U[i] = matrix[vs][i]; // 顶点i与顶点vs的初始距离为"顶点vs"到"顶点i"的权。也就是邻接矩阵vs行的数据。 prev[i] = 0; //顶点i的前驱顶点为0
} // 将vs从U中“移除”(U与flag配合使用)
flag[vs] = true;
U[vs] = 0;
// 将vs顶点加入S
S[0] = vertexes[vs];
// 步骤一结束 //步骤四:重复步骤二三,直到遍历完所有顶点。
// 遍历vertexes.length-1次;每次找出一个顶点的最短路径。
int k = 0;
for (int i = 1; i < vertexes.length; i++) {
// 步骤二:从U中找出路径最短的顶点,并将其加入到S中(如果vs顶点到x顶点还有更短的路径的话,那么
// 必然会有一个y顶点到vs顶点的路径比前者更短且没有加入S中
// 所以,U中路径最短顶点的路径就是该顶点的最短路径)
// 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
int min = MAX_WEIGHT;
for (int j = 0; j < vertexes.length; j++) {
if (flag[j] == false && U[j] < min) {
min = U[j];
k = j;
}
} //将k放入S中
S[i] = vertexes[k]; //步骤二结束 //步骤三:更新U中的顶点和顶点对应的路径
//标记"顶点k"为已经获取到最短路径(更新U中的顶点,即将k顶点对应的flag标记为true)
flag[k] = true; //修正当前最短路径和前驱顶点(更新U中剩余顶点对应的路径)
//即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
for (int j = 0; j < vertexes.length; j++) {
//以k顶点所在位置连线其他顶点,判断其他顶点经过最短路径顶点k到达vs顶点是否小于目前的最短路径,是,更新入U,不是,不做处理
int tmp = (matrix[k][j] == MAX_WEIGHT ? MAX_WEIGHT : (min + matrix[k][j]));
if (flag[j] == false && (tmp < U[j])) {
U[j] = tmp;
//更新 j顶点的最短路径前驱顶点为k
prev[j] = k;
}
}
//步骤三结束
}
//步骤四结束 // 打印dijkstra最短路径的结果
System.out.println("起始顶点:" + vertexes[vs]);
for (int i = 0; i < vertexes.length; i++) {
System.out.print("最短路径(" + vertexes[vs] + "," + vertexes[i] + "):" + U[i] + " "); List<String> path = new ArrayList<>();
int j = i;
while (true) {
path.add(vertexes[j]); if (j == 0)
break; j = prev[j];
} for (int x = path.size()-1; x >= 0; x--) {
if (x == 0) {
System.out.println(path.get(x));
} else {
System.out.print(path.get(x) + "->");
}
} } System.out.println("顶点放入S中的顺序:");
for (int i = 0; i< vertexes.length; i++) { System.out.print(S[i]); if (i != vertexes.length-1)
System.out.print("-->");
} } public static void main(String[] args) {
ShortestPathDijkstra dij = new ShortestPathDijkstra();
dij.createGraph(9);
dij.dijkstra(0);
} }

参考:https://blog.csdn.net/CmdSmith/article/details/56839285

[数据结构]迪杰斯特拉(Dijkstra)算法的更多相关文章

  1. 迪杰斯特拉Dijkstra算法介绍

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijk ...

  2. JS实现最短路径之迪杰斯特拉(Dijkstra)算法

    最短路径: 对于网图来说,最短路径是指两个顶点之间经过的边上权值和最少的路径,我们称第一个顶点是源点,最后一个顶点是终点 迪杰斯特拉 ( Dijkstra) 算法是并不是一下子就求出 了 Vo 到V8 ...

  3. 最短路径算法-迪杰斯特拉(Dijkstra)算法在c#中的实现和生产应用

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思想),直到扩展到终点为止 贪心算法(Greedy ...

  4. 最短路径-迪杰斯特拉(dijkstra)算法及优化详解

    简介: dijkstra算法解决图论中源点到任意一点的最短路径. 算法思想: 算法特点: dijkstra算法解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树.该算法常用于路由算 ...

  5. 最短路径 - 迪杰斯特拉(Dijkstra)算法

    对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd ...

  6. C# 迪杰斯特拉(Dijkstra)算法

    Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 其基本思想是,设置顶点集合S并不断地作 ...

  7. 图的最短路径---迪杰斯特拉(Dijkstra)算法浅析

    什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...

  8. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)

    一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...

  9. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(一)

    一.算法介绍 迪杰斯特拉算法(英语:Dijkstra's algorithm)由荷兰计算机科学家艾兹赫尔·迪杰斯特拉在1956年提出.迪杰斯特拉算法使用了广度优先搜索解决赋权有向图的单源最短路径问题. ...

  10. 迪杰斯特拉(Dijkstra)算法

    # include <stdio.h> # define MAX_VERTEXES //最大顶点数 # define INFINITY ;//代表∞ typedef struct {/* ...

随机推荐

  1. ||在oracle数据库中起到字符串拼接的作用

    例子:select org.id from org where inner_code like '12011601001' || '%' ||在oracle数据库中起到字符串拼接的作用,上面等同于'1 ...

  2. HTTP报文头Accept和Content-Type总结

    1.Accept属于请求头, Content-Type属于实体头. Http报头分为通用报头,请求报头,响应报头和实体报头. 请求方的http报头结构:通用报头|请求报头|实体报头 响应方的http报 ...

  3. JDK1.6新特性,基础类库篇,IO支持

    1. JDK1.6中提供了java.io.Console类 JDK1.6中提供了java.io.Console 类专用来访问基于字符的控制台设备.你的程序如果要与Windows下的cmd或者Linux ...

  4. 不应直接存储或返回可变成员 Mutable members should not be stored or returned directly

    Mutable objects are those whose state can be changed. For instance, an array is mutable, but a Strin ...

  5. 【Unity】11.4 车轮碰撞体(Wheel Collider)

    分类:Unity.C#.VS2015 创建日期:2016-05-02 一.简介 车轮碰撞体 (Wheel Collider)专门用于创建汽车或其他移动交通工具. 车轮碰撞体是一种针对地面车辆的特殊碰撞 ...

  6. Capterra Software Categories

    https://www.capterra.com/categories this software categories is valuable.

  7. angular-resource版本差异问题

    在 AngularJS v1.3.0-beta.14 这个版本里,使用query方法,如果传递进来的数据不是数组,会报错. 在 AngularJS v1.2.18 这个版本里,使用query方法,如果 ...

  8. Function.apply()在提升程序性能方面的技巧

    我们先从Math.max()函数说起,Math.max后面可以接任意个参数,最后返回所有参数中的最大值. 比如 alert(Math.max(5,8))   //8alert(Math.max(5,7 ...

  9. MVC的项目部署成应用程序或虚拟目录路径的问题

    1.js和css的引用出错 a.~/可以取得应用程序目录 b. ./定位到路径,./代表到本目录,../代表父级目录 2.打开页面view a. ./定位到路径 3.img src   a. ./定位 ...

  10. c++ primer读书笔记之c++11(三)

    1 =default构造函数限定符 c++11针对构造函数提供了=default限定符,可以用于显式指定编译器自动生成特定的构造函数.析构或赋值运算函数.参考代码如下: class CtorDftTy ...