Dijkstra’s shortest path algorithm

算法参考地址:Dijsktra's algorithm (geeksforgeeks.org)

算法的简介:

1)该算法用来计算最短距离,但不计算路径信息。我们可以创建一个父数组,在距离更新时更新父数组如[prim的实现,并使用它来显示从源到不同顶点的最短路径。 2)代码用于无向图,相同的Dijkstra函数也可以用于有向图。 3) 代码查找从源到所有顶点的最短距离。如果我们只对从源到单个目标的最短距离感兴趣,我们可以在选取的最小距离顶点等于目标时中断for循环(算法的步骤3.a)。 4) 实现的时间复杂度为 O(V^2)。如果输入,则可以借助二进制堆将其简化为 O(E log V)。 5)Dijkstra的算法不适用于具有负权重周期的图形。对于具有负边的图形,可以使用Floyd或者Bellman-Ford算法。

算法的过程

给定图形和图形中的源顶点,查找从源到给定图形中所有顶点的最短路径。 Dijkstra的算法与[Prim的最小生成树算法]非常相似。与Prim的MST一样,我们生成一个SPT(最短路径树),以给定的源作为根。我们维护两个集合,一个集合包含最短路径树中包含的顶点,另一个集合包含尚未包含在最短路径树中的顶点。在算法的每一步中,我们都会找到一个位于另一个集合(尚未包含的集合)中的顶点,并且与源的距离最小。 以下是Dijkstra算法中使用的详细步骤,用于查找从单个源顶点到给定图中所有其他顶点的最短路径。

算法 1) 创建一个集合 sptSet(最短路径树集),用于跟踪最短路径树中包含的顶点,即计算并最终确定其与源的最小距离。最初,此集为空。 2) 为输入图中的所有顶点分配距离值。将所有距离值初始化为 INFINITE。为源顶点指定距离值为 0,以便首先选取它。 3) 虽然 sptSet 不包括所有顶点 ....a) 选择一个在 sptSet 中不存在且具有最小距离值的顶点 u。 ....b) 将您包括在 sptSet 中。 ....c) 更新您所有相邻顶点的距离值。要更新距离值,请循环访问所有相邻顶点。对于每个相邻顶点 v,如果 u 的距离值(来自源)和边 u-v 的权重之和小于 v 的距离值,则更新 v 的距离值。

让我们通过以下示例来理解:

设置的 sptSet 最初是空的,分配给顶点的距离是 {0, INF, INF, INF, INF, INF, INF} ,其中 INF 表示无限。现在选取具有最小距离值的顶点。选取顶点 0,将其包含在 sptSet 中。所以sptSet变得{0}。在 sptSet 中包含 0 后,更新其相邻顶点的距离值。相邻顶点 0 为 1 和 7。距离值 1 和 7 将更新为 4 和 8。以下子图显示顶点及其距离值,仅显示具有有限距离值的顶点。SPT 中包含的顶点以绿色显示。

选取具有最小距离值且尚未包含在 SPT(不在 sptSET 中)的顶点。选取顶点 1 并将其添加到 sptSet 中。所以 sptSet 现在变成 {0, 1}。更新相邻顶点 1 的距离值。顶点 2 的距离值变为 12。

选取具有最小距离值且尚未包含在 SPT(不在 sptSET 中)的顶点。选取顶点 7。所以 sptSet 现在变成 {0, 1, 7}。更新相邻顶点的距离值 7。顶点 6 和 8 的距离值变为有限(分别为 15 和 9)。

选取具有最小距离值且尚未包含在 SPT(不在 sptSET 中)的顶点。选取顶点 6。所以 sptSet 现在变成 {0, 1, 7, 6}。更新相邻顶点 6 的距离值。将更新顶点 5 和 8 的距离值。

我们重复上述步骤,直到 sptSet 包含给定图形的所有顶点。最后,我们得到以下最短路径树(SPT)。

我们使用布尔数组 sptSet[] 来表示 SPT 中包含的顶点集。如果值 sptSet[v] 为真,则顶点 v 包含在 SPT 中,否则不包含。数组 dist[] 用于存储所有顶点的最短距离值。

算法的实现

golang

// F 代表两点之间不可达
const F = 10000
func dijkstra(graph [][]int, source int) []int {
  n := len(graph)
  if source >= n {
     return []int{}
  }
  dist := make([]int, n)
  visited := make([]bool, n)
  for i := 0; i < n; i++ {
     dist[i] = graph[source][i]
     visited[i] = false
  }
  dist[source] = 0
  visited[source] = true

  for i := 1; i < n; i++ {
     temMinDis := F
     curIdx := -1
     for j := 0; j < n; j++ {
        if !visited[j] && dist[j] < temMinDis {
           temMinDis = dist[j]
           curIdx = j
        }
    }
     visited[curIdx] = true
     dist[curIdx] = temMinDis
     for k := 0; k < n; k++ {
        if !visited[k] && dist[curIdx]+graph[curIdx][k] < dist[k] {
           dist[k] = dist[curIdx] + graph[curIdx][k]
        }
    }
  }
  return dist
}

Java

package graph.dijkstra;

import java.util.Arrays;

public class ShortestPathOfDijkstra {
   private static final int MAX = 10000;

   /**
    * 接受一个有向图的权重矩阵,和一个起点编号start(从0编号,顶点存在数组中)
    *
    * @param graph           graph
    * @param startPointIndex startPointIndex
    * @return 返回一个int[] 数组,表示从start到它的最短路径长度
    */
   public static int[] dijsktra(int[][] graph, int startPointIndex) {
       int length = graph.length;
       //标记当前该顶点的最短路径是否已经求出,true表示已经求出
       boolean[] visited = new boolean[length];
       //start点的最短距离已经求出
       for (int i = 0; i < graph.length; i++) {//初始化s集合,只有起始点
           if (i == startPointIndex) {
               visited[i] = true;
          } else {
               visited[i] = false;
          }
      }

       //存放从start到各个点的最短距离
       int[] shortDistance = new int[length];

       for (int i = 0; i < graph.length; i++) {//初始化,起始点到其他点的距离。
           shortDistance[i] = graph[startPointIndex][i];
      }

       //start到他本身的距离最短为0
       shortDistance[startPointIndex] = 0;


       //存放从start点到各点的最短路径的字符串表示
       String[] path = new String[length];
       for (int i = 0; i < length; i++) {
           path[i] = startPointIndex + "->" + i;
      }

       for (int count = 1; count < length; count++) {
           int k = -1;
           int dmin = MAX;
           for (int i = 0; i < length; i++) {
               if (!visited[i] && shortDistance[i] < dmin) {
                   dmin = shortDistance[i];
                   k = i;
              }
          }
           //选出一个距离start最近的未标记的顶点     将新选出的顶点标记为以求出最短路径,且到start的最短路径为dmin。
           shortDistance[k] = dmin;
           visited[k] = true;
           //以k为中间点,修正从start到未访问各点的距离
           for (int i = 0; i < length; i++) {
               if (!visited[i] && shortDistance[k] + graph[k][i] < shortDistance[i]) {
                   shortDistance[i] = shortDistance[k] + graph[k][i];
                   path[i] = path[k] + "->" + i;
              }
          }
      }
       for (int i = 0; i < length; i++) {
           System.out.println("从" + startPointIndex + "出发到" + i + "的最短路径为:" + path[i] + "=" + shortDistance[i]);
      }
       return shortDistance;
  }

   public static void main(String[] args) {
       int[][] graph = {
              {0, 4, 6, 6, MAX, MAX, MAX},
              {MAX, 0, 1, MAX, 7, MAX, MAX},
              {MAX, MAX, 0, MAX, 6, 4, MAX},
              {MAX, MAX, 2, 0, MAX, 5, MAX},
              {MAX, MAX, MAX, MAX, 0, MAX, 6},
              {MAX, MAX, MAX, MAX, 1, 0, 8},
              {MAX, MAX, MAX, MAX, MAX, MAX, MAX}};
       int start = 0;
       int[] dijsktra = dijsktra(graph, start);
       System.out.println(Arrays.toString(dijsktra));
  }
}

图最短路径之Dijkstra的更多相关文章

  1. 算法学习记录-图——最短路径之Dijkstra算法

    在网图中,最短路径的概论: 两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点. 维基百科上面的解释: 这个算法是通过为每个顶点 v 保留目前为止所找到的从 ...

  2. 有向有权图的最短路径算法--Dijkstra算法

    Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Di ...

  3. Dijkstra含权图最短路径;审判,不要错过枚举退款保证不会重复;国际象棋八皇后问题

    求两节点的最短通路.对于无权图,能够通过图的广度优先遍历求解.含权图一般通过Dijkstra算法求解. import java.util.ArrayList; import java.util.Has ...

  4. 最短路径算法Dijkstra和A*

    在设计基于地图的游戏,特别是isometric斜45度视角游戏时,几乎必须要用到最短路径算法.Dijkstra算法是寻找当前最优路径(距离原点最近),如果遇到更短的路径,则修改路径(边松弛). Ast ...

  5. 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson

    根据DSqiu的blog整理出来 :http://dsqiu.iteye.com/blog/1689163 PS:模板是自己写的,如有错误欢迎指出~ 本文内容框架: §1 Dijkstra算法 §2 ...

  6. 单源最短路径(dijkstra算法)php实现

    做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...

  7. 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)

    一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...

  8. 最短路径算法——Dijkstra算法

    在路由选择算法中都要用到求最短路径算法.最出名的求最短路径算法有两个,即Bellman-Ford算法和Dijkstra算法.这两种算法的思路不同,但得出的结果是相同的. 下面只介绍Dijkstra算法 ...

  9. 最短路径之Dijkstra算法和Floyd-Warshall算法

    最短路径算法 最短路径算法通常用在寻找图中任意两个结点之间的最短路径或者是求全局最短路径,像是包括Dijkstra.A*.Bellman-Ford.SPFA(Bellman-Ford的改进版本).Fl ...

  10. 【算法设计与分析基础】25、单起点最短路径的dijkstra算法

    首先看看这换个数据图 邻接矩阵 dijkstra算法的寻找最短路径的核心就是对于这个节点的数据结构的设计 1.节点中保存有已经加入最短路径的集合中到当前节点的最短路径的节点 2.从起点经过或者不经过 ...

随机推荐

  1. 揭露 FileSystem 引起的线上 JVM 内存溢出问题

    作者:来自 vivo 互联网大数据团队-Ye Jidong 本文主要介绍了由FileSystem类引起的一次线上内存泄漏导致内存溢出的问题分析解决全过程. 内存泄漏定义(memory leak):一个 ...

  2. SpringBoot使用JSch操作Linux

    推荐使用Hutool的Jsch工具包(它用的连接池的技术) 一.SSH远程连接服务器 SSH更多见:http://t.csdnimg.cn/PrsNv 推荐连接工具:FinalShell.Xshell ...

  3. 4.10 + (double)(rand()%10)/100.0

    黑色星期四 坏消息: 没有奥赛课,所以大概率调不出来 CF1479D 好消息: 5k 回来了,调题有望 中午起床直接来的机房,有学科自习就说 氟硫氢 不知道 结果被叫回去了 而且今天班里没水了,趁着大 ...

  4. Ubuntu(Linux)虚拟机与主机共享文件夹hgfs文件普通用户不能访问问题

    参考文章: https://blog.csdn.net/weixin_42224577/article/details/108107554 在虚拟机中设置好添加共享文件后,普通用户并不能访问mnt文件 ...

  5. vben集成keycloak

    前言 公司的项目是vben admin框架需要集成keycloak,那keycloak大家应该都不陌生了,就是统一认证的一个系统简称IDS.之前用过cas,并重构过cas的前端界面,所以对此也是比较熟 ...

  6. IDEA文件夹注释插件TreeInfotip使用

    目录 前景提要 环境整合 构建工具(参考工具部署方式) 下载插件 使用 前景提要 很多开源代码或者公司代码,因为层级比较多,所以查阅困难,发现一个TreeInfotip插件可以对这样的文件做注释 环境 ...

  7. 读写可编程 SIM/USIM 卡

    目录 文章目录 目录 SIM 卡 USIM 卡 USIM 卡的关键参数 pySim 读写软件与 ADM key SIM 卡 SIM 卡,用户身份模块(Subscriber Identity Modul ...

  8. Python基础篇(安装)

    Python简介 Python是Guido van Rossum发布于1991年的一种计算机程序设计语言.是一种动态的.面向对象的脚本语言,是一种解释型的,弱类型的高级计算机语言.需要注意的是pyth ...

  9. Vue cli单文件组件的使用

    整个项目是一个主文件index.html,index.html中会引入src文件夹中的main.js,main.js中会导入顶级单文件组件App.vue,App.vue中会通过组件嵌套或者路由来引用其 ...

  10. NOIP模拟90(多校23)

    T1 回文 解题思路 原来 \(n^3\) 可以过 500 ... 先枚举一下路径长度,对于同一路径长度点数最多是 \(n\) 个,我们可以接着枚举从 \((n,m)\) 出发的路径长度相同的点. 然 ...