算法之迪杰斯特拉算法

news/2024/11/24 1:53:03/

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

迪杰斯特拉算法思想

设G=(V,E)为一个带全有向图,把图中顶点集合V分成两组。第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将所到达最短路径的顶点加入到集合S中,直到全部顶点都加入到S中)。第二组为其余未确定最短路径的顶点集合(用U表示,U=V-S,U中的顶点不断的加入到S中,直到U为空,S=V)。在U加入S的过程中,始终保持源点到S中各顶点的最短路径长度小于或等于源点到U中任意顶点的最短路径长度。

迪杰斯特拉算法要求边的权值不能为负数

迪杰斯特拉采用的贪心策略,设S集合中是已经计算出最短路径的节点,T集合中是未计算出最短路径的节点。假设存在负权,源点为A,已经计算出A->B的最短路径为m,若下一次将C添加进已计算出最短路径的节点集合,而A->C=m,C->B=-1,则会出现A->B的更短路径A->C->B,迪杰斯特拉不会对已经计算出最短路径的节点重新计算,因此无法更新最短路径,即负权的出现导致无法保证S中节点计算的是最短路径。

迪杰斯特拉算法步骤

1 定义个优先级队列,将起始顶点放入队列;

2 从队列里取出一个顶点,并设置该顶点已经访问

3 循环找到该顶点的邻接顶点 。 先统计邻节点所对应的路径权值,放入dis路径数组

4 从邻节点dis路径数组中找出dis的最小值, 下一次从未访问过、并且可以访问的最近的dis最短的结点开始(广度优先);找到最小值后将此顶点放入优先级队列

5 重复直到优先级队列为空为止

迪杰斯特拉算法图解

动图
在这里插入图片描述迪杰斯特拉算法在运行过程中 需要维持一组节点集合S,从源节点s到该集合每个节点之间的最短路径已经找到。算法重复从节点集合V-S中选择权值最小的节点u,将u设置已访问并加入到集合S. 然后从该顶点开始进行下轮寻找最小权值。其算法伪代码:

在这里插入图片描述

在这里插入图片描述
源节点s为最左边的节点,也就是我们设置的起始顶点,数值代表其边对应的权值。加阴影的边代表前驱值,黑色节点属于S集合,白色节点属于优先级队列里的节点;(a)为上图伪代码中4-8行循环首次执行的场景,阴影为节点距离值dis最小的节点,该节点在伪代码第5行被放入优先级队列 (b)-(f) 为成功执行while循环后的场景,所有图中加阴影的节点都是从优先级队列选出的节点作为下一次循环所用的节点;迪杰斯特拉算法每次都是从集合V-S中选择最近,权值最小的节点加入到集合S中,体现贪心策略。但是迪杰斯特拉不会对已经计算出最短路径的节点重新计算,因此无法更新最短路径,导致出现负权的无法保证S中节点计算的是最短路径。

代码实现

class  DijkstraGraph{int[][] matrix;int vertexNum;public DijkstraGraph(int vertexNum) {this.vertexNum = vertexNum;matrix = new int[vertexNum][vertexNum];}public void addEdge(int start,int end,int weight){matrix[start][end] = weight;matrix[end][start] = weight;}}

迪杰斯特拉算法

 private   void  dijkstra(DijkstraGraph graph,int beginIndex){int minDistance = 0;dis[beginIndex] = 0;isVisited[beginIndex] = true;PriorityQueue<Integer> queue = new PriorityQueue<>();queue.offer(beginIndex);while (queue.size() > 0) {int  index = queue.poll();isVisited[index] = true;for (int j = 0; j < graph.vertexNum; j++) {if ( graph.matrix[index][j] != 0 && !isVisited[j]){//先统计邻节点所对应的路径权值//当有更短的路径方案时,替换路径值和方案dis[j] = Math.min(graph.matrix[index][j] + minDistance,dis[j]);}}minDistance = Integer.MAX_VALUE;for (int j = 0; j < dis.length; j++) {//从邻节点路径权值找出dis的最小值, 下一次从未访问过、并且可以访问的最近的dis最短的结点开始(广度优先)if(!isVisited[j] && dis[j] < minDistance) {minDistance = dis[j];index = j;}}if (!isVisited[index]) queue.offer(index);}}

http://www.ppmy.cn/news/527556.html

相关文章

迪杰斯特拉模板

迪杰斯特拉算法求无向图最短路 #include<cstring> #include<cstdio> #include<algorithm> #define inf 99999999 #define N 1010 using namespace std; int map[N][N];//原储存矩阵 int dist[N]; int visited[N],s[N]; int n,m;void Dijkstra(int J)//求每个…

迪杰斯特拉算法(入门理解)

Dijkstra算法&#xff08;求某一个点到其他点的最短距离&#xff09;&#xff1a; *南昌理工学院ACM暑假集训队 &#x1f603; Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法&#xff0c;用于计算一个节点到其他所有节点的最短路径。 主要特点是以起始点为中心向外层层扩…

如何理解迪杰斯特拉算法

路漫漫其修远兮&#xff0c;吾将上下而求索。                 ——屈原 在最短路径的求解算法中&#xff0c;迪杰斯特拉&#xff08;Dijkstra&#xff09;算法应该是非常出名的&#xff0c;但是对于初学者而言却又很难理解为什么这个算法是对的&#xff0c;找…

算法系列——迪杰斯特拉算法(Dijkstra)

本系列旨在用简单的人话讲解算法&#xff0c;尽可能避免晦涩的定义&#xff0c;读者可以短时间内理解算法原理及应用细节。我在努力&#xff01; 本篇文章编程语言为Python&#xff0c;供参考。 迪杰斯特拉算法&#xff08;Dijkstra&#xff09; 典型最短路径算法。用于计算一…

迪杰特斯拉算法

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法&#xff0c;这个算法我主动学了三遍&#xff0c;第一主动学的时候&#xff0c;是看严蔚敏的《数据结构》&#xff0c;当时应该是学懂了&#xff0c;有点透彻地理解了这个算法&#xff0c;但是没有记录下来&#xff0c;后来就…

迪杰斯特拉算法-(.c)

一、定义 Dijkstra算法&#xff08;迪杰斯特拉算法&#xff09;是很有代表性的最短路径算法&#xff0c;用于计算一个结点到其他结点的最短路径。该算法指定一个点&#xff08;源点&#xff09;到其余各个结点的最短路径&#xff0c;因此也叫做单源最短路径算法。该算法是由荷…

经典迪杰斯特拉算法

参数说明&#xff1a; n&#xff0c;城市的数量 m&#xff0c;边的数量 maxint&#xff0c;认为定义的一个认为是断路的标志 maxnum一个宏 dist[]纪录其他个点到出发点的距离&#xff0c;程序没有把算法写成函数&#xff0c;而是最简单的流水线执行&#xff0c;以0号城市为出发…

迪杰斯特拉算法详解

1.概述&#xff1a;Dijkstra算法是用来寻找两点之间最短路径的算法&#xff0c;在实际生活中有着很大的作用他的思想就是选定一点然后向后遍历直至所有点到选定点的最短距离全部求处为止。 2.算法思想&#xff1a; &#xff08;1&#xff09;初始化&#xff1a;先找处从源点V0到…