迪杰斯特拉算法(dijkstra)

news/2024/11/23 23:29:58/

 算法背景:

图中的A,B,C,D,E,F,G,代表7个村庄,边上的权值带表两村庄之间的距离,现在要从某一个村庄,例如G村庄,往另外几个村庄送邮件,问G村庄到其他各村庄的最短距离分别是多少?

思路:

该问题实际是求从某一顶点到其余顶点的最短距离,即单源点到其余顶点的距离。可以用迪杰斯特拉算法求解。

dijkstra算法求最短距离

算法思路:

该算法使用了三个辅助数组,首先应理解它们的含义:

  • visited[]:保存各顶点是否被访问过,初始时,除了其实顶点为true外,其余都是false。
  • distance[]:存放动态的单源点到其余点的最短距离,初始时为单源点到各店的距离,其中单源点自身距离设置为0。
  • prePath[]:保存当前结点的前驱结点,方便最后找最短距离的路径,初始时除与单源点有直接路径的顶点设置为单源点索引外其余都设置为-1,即没有前驱点。

 该算法将图中顶点分为两类:已访问过的和没访问过的,这里的已访问过是指对应顶点的distance中的距离已经是真实的最短的距离了,通过visited中的true和false实现。初始时,只有起始顶点为true,然后在false的顶点中找出动态距离最短的顶点(体现贪心思想),将其置为true,此时访问该点的邻接边,并对比“过渡距离”是否小于distance中的距离,小于则更新distance和prePath。依次循环直到都置为true为止。

 核心代码:

算法分析:

该算法用了两层for,外层为需要访问的顶点个数,时间复杂度为O(n),内层有两个for,第一个for为挑选未被访问的顶点的最短距离,时间复杂度为O(n),第二个for为在与选中顶点有直接路径的顶点中对比距离是否需要更新,时间复杂度为O(n),所以总的时间复杂度为O(n²)。

dijkstra算法可通过改变存储结构(邻接表)和存储距离(优先队列)的方式做优化,使最后复杂度为O(nlogn)。

具体见:迪杰斯特拉算法优化(dijkstra)icon-default.png?t=L9C2https://blog.csdn.net/weixin_48898946/article/details/121004513

public void dijkstra(int index) {for(int i = 0; i < numOfVertex;i++) {//初始化各辅助数组distant[i] = edge[index][i];if(edge[index][i] != INF) {prePath[i] = index;}else {prePath[i] = -1;}}visit[index] = true;//置初始起点已访问for(int i = 0; i < numOfVertex - 1;i++) {int des = 0;int minDis = INF;for(int j = 0; j < numOfVertex ;j++) {//挑选为被访问的最短距离的顶点if(visit[j] == false && minDis > distant[j]) {minDis = distant[j];des = j;}}visit[des] = true;//更新为已访问for(int j = 0; j < numOfVertex;j++) {//对比更新最短距离int len = edge[des][j] + distant[des];if(len < distant[j] && len < INF) {distant[j] = len;prePath[j] = des;}}}System.out.printf("顶点%c到其余各点的最短距离:\n",vertex[index]);for (int i = 0; i < numOfVertex; i++) {if (i != index) {System.out.printf("顶点%c到顶点%c的最短距离是%d\n", vertex[index], vertex[i], distant[i]);}}System.out.println();
}

java代码:

import java.util.*;public class Dijkstra {public static void main(String[] args) {final int INF = 0x3f3f3f3f;char[]vertex = {'A','B','C','D','E','F','G'};int [][]edge = new int [][] {{INF,5,7,INF,INF,INF,2},{5,INF,INF,9,INF,INF,3},{7,INF,INF,INF,8,INF,INF},{INF,9,INF,INF,INF,4,INF},{INF,INF,8,INF,INF,5,4},{INF,INF,INF,4,5,INF,6},{2,3,INF,INF,4,6,INF}};Graph graph = new Graph(vertex, edge);graph.printGraph();System.out.println("\n初始起点为G点:\n");graph.dijkstra(6);graph.printPath(6);}
}
class Graph{final int INF = 0x3f3f3f3f;//设置一个“大数”char []vertex;//顶点数组int [][]edge;//邻接矩阵int numOfVertex;//顶点个数boolean []visit;//访问标志数组int []distant;//最短距离数组int []prePath;//最短路径前驱数组public Graph(char[] vertex, int[][] edge) {this.vertex = vertex;this.edge = edge;numOfVertex = vertex.length;visit = new boolean[numOfVertex];distant = new int [numOfVertex];prePath = new int [numOfVertex];}public void printGraph() {System.out.println("邻接矩阵为:");for(int[] data : edge) {System.out.println(Arrays.toString(data));}}public void dijkstra(int index) {for(int i = 0; i < numOfVertex;i++) {//初始化各辅助数组distant[i] = edge[index][i];if(edge[index][i] != INF) {prePath[i] = index;}else {prePath[i] = -1;}}visit[index] = true;//置初始起点已访问for(int i = 0; i < numOfVertex - 1;i++) {int des = 0;int minDis = INF;for(int j = 0; j < numOfVertex ;j++) {//挑选为被访问的最短距离的顶点if(visit[j] == false && minDis > distant[j]) {minDis = distant[j];des = j;}}visit[des] = true;//更新为已访问for(int j = 0; j < numOfVertex;j++) {//对比更新最短距离int len = edge[des][j] + distant[des];if(len < distant[j] && len < INF) {distant[j] = len;prePath[j] = des;}}}System.out.printf("顶点%c到其余各点的最短距离:\n",vertex[index]);for (int i = 0; i < numOfVertex; i++) {if (i != index) {System.out.printf("顶点%c到顶点%c的最短距离是%d\n", vertex[index], vertex[i], distant[i]);}}System.out.println();}public void printPath(int m) {for(int i = 0; i < numOfVertex;i++) {if(i == m) continue;int []flag = new int[numOfVertex];int index = 0;flag[index++] = i;int k = i;while(true) {k = prePath[k];if(k == m || k == -1)break;flag[index++] = k;}flag[index] = m;System.out.printf("顶点%c到顶点%c的最短路径为:",vertex[m],vertex[i]);for(int j = index; j >= 0; j--) {System.out.print(vertex[flag[j]] + " ");}System.out.println();}}
}

程序输出:

邻接矩阵为:
[1061109567, 5, 7, 1061109567, 1061109567, 1061109567, 2]
[5, 1061109567, 1061109567, 9, 1061109567, 1061109567, 3]
[7, 1061109567, 1061109567, 1061109567, 8, 1061109567, 1061109567]
[1061109567, 9, 1061109567, 1061109567, 1061109567, 4, 1061109567]
[1061109567, 1061109567, 8, 1061109567, 1061109567, 5, 4]
[1061109567, 1061109567, 1061109567, 4, 5, 1061109567, 6]
[2, 3, 1061109567, 1061109567, 4, 6, 1061109567]初始起点为G点:顶点G到其余各点的最短距离:
顶点G到顶点A的最短距离是2
顶点G到顶点B的最短距离是3
顶点G到顶点C的最短距离是9
顶点G到顶点D的最短距离是10
顶点G到顶点E的最短距离是4
顶点G到顶点F的最短距离是6顶点G到顶点A的最短路径为:G A 
顶点G到顶点B的最短路径为:G B 
顶点G到顶点C的最短路径为:G A C 
顶点G到顶点D的最短路径为:G F D 
顶点G到顶点E的最短路径为:G E 
顶点G到顶点F的最短路径为:G F 


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

相关文章

算法之迪杰斯特拉算法

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

迪杰斯特拉模板

迪杰斯特拉算法求无向图最短路 #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号城市为出发…