dijkstra算法详解—简单易懂[通俗易懂]

dijkstra算法详解—简单易懂[通俗易懂]dijkstra算法详解(迪杰斯特拉算法)~~简单易懂,代码附有详细注释,含动态演示图片

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

1 简介

迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。这是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止
PS:此算法不能用于求负权图,要求所有边的权重都为非负值。


2 算法思想与原理

dijkstra算法思想是基于贪心算法思想的。所谓贪心算法即始终保持当前迭代解为当前最优解。意思就是在已知的条件下或是当前拥有的全部条件下保证最优解,若在此后的迭代中由于加入了新的条件使得产生了更优解则替代此前的最优解。通过不断的迭代不断保证每次迭代的结果都是当前最优解,那么当迭代到最后一轮时得到的就会是全局最优解。 由于下一轮迭代会参考上一轮的最优解,因此每一轮的迭代的工作量基本一致,降低了整体工作的复杂性。

在最短路径的问题中,局部最优解即当前的最短路径或者说是在当前的已知条件下起点到其余各点的最短距离。关键就在于已知条件,这也是Dijkstra算法最精妙的地方。我们来解释一下。

对于Dijkstra算法,我们假设初始集合(也就是初始条件)不存在任何顶点的,即所有顶点之间是不存在任何路径的,即我们认为所有顶点之间的距离都是无穷大。那么开始加入新的条件,因为我们已知源点距源点距离最小,所以加入进去,并加入它的边,在该条件下,更新该源点到其余顶点的最短距离,选出没有加入到已知集合的距源点距离最小的点,此点最短距离也被确定了(因为其他路径都比这条路径大,无法通过其他路径间接到达这个顶点使得路径更小),然后加入该点与其余还未加入已知条件顶点的边,并以该点迭代刷新最短距离。再重复以上操作,直至所有顶点都加入已知条件集合。


3 具体步骤

  1. 选择起点start与终点end;
  2. 所有点除起点外加入未知集合,并将起点加入已知集合,即至标志位为真,意为已确定该点到源点的最短路径;
  3. 初始化计算,更新起点与其他各点的耗费dis(start,n);
  4. 在未知集合中,选择dis(start,n)中值最小的点x,将x加入已知集合。
  5. 对于剩余顶点中,计算dis(start,n)>dis(start,x)+dis(x,n)
    若真则dis(start,n)=dis(start,x)+dis(x,n),此时start与n点路径经过x点。循环直至goal点加入已知列表,取得dis(start,goal)即为最短距离。

4 动态展示

在这里插入图片描述

5 代码实现(以邻接矩阵为例)

5.1 基本数据

const int inf=0x3f3f3f3f; //代表无穷大。
const int maxn=100;//最大顶点数
int n,m;//n个顶点,m条边。
bool visited[maxn];//判断是否确定到源点的最终最短距离。
int graph[maxn][maxn];//带权图
int dis[maxn];//顶点到源点的最短距离。
int start,goal;//起点与目标点。

Jetbrains全家桶1年46,售后保障稳定

5.2 初始化

void init(){ 
   
	memset(visited,false,sizeof(visited));
	for(int i=1;i<=n;i++){ 
   
		dis[i]=graph[start][i];//初始化dis数组。
	}
}

5.3 dijkstra算法核心

void dijkstra(){ 
   
	//源点为源点start。
	int minn;//记录每趟最短路径中最小的路径值。 
	int pos;//记录得到的minn所对应的下标。
	init();//调用初始化函数。
	visited[start]=true;
	for(int i=1;i<=n;i++){ 
   
		//将n个顶点依次加入判断。
		minn=inf;
		for(int j=1;j<=n;j++){ 
   
			if(!visited[j]&&dis[j]<minn){ 
   
				minn=dis[j];
				pos=j;
			}
		}
		//经过这趟for循环后我们找到的就是我们想要的点,可以确定这点到源点的最终最短距离了。
		visited[pos]=true;//我们将此点并入已知集合。
		//接下来就是更新dis数组了,也就是当前最短距离,这都是针对还没有并入已知集合的点。
		for(int j=1;j<=n;j++){ 
   
			if(!visited[j]&&dis[j]>dis[pos]+graph[pos][j])
				dis[j]=dis[pos]+graph[pos][j];
		}
	}
	//退出循环后,所有的点都已并入已知集合中,得到的dis数组也就是最终最短距离了。
	cout<<dis[goal]<<endl;//输出目标点到源点的最短路径长度。
}

5.4 主函数与头文件等

#include<bits/stdc++.h>

using namespace std;

int main()
{ 
   
    while(cin>>n>>m){ 
   
		memset(graph,inf,sizeof(graph));
		int u,v,w;
		for(int i=0;i<m;i++){ 
   
			cin>>u>>v>>w;
// graph[u][v]=w;//有向图
			graph[u][v]=graph[v][u]=w;//无向图
		}
		cin>>start>>goal;//输入起点与终点。
		dijkstra();
    }
    return 0;
}

6 拓展

如果你学会了dijkstra,那恭喜你成功突破了一关。但是,没有优化的dijkstra算法时间复杂度为 O ( n 2 ) O(n^2) O(n2),如果顶点很多边很少呢等等卡邻接矩阵的题,那么建议你还是要学一下dijkstra的优化版了。详情点击:Dijkstra算法优化~~你一定可以看懂的四种进阶优化

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/203541.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java有全局变量吗_java局部变量和成员变量的区别

    java有全局变量吗_java局部变量和成员变量的区别//    java全局变量危害 //    最近为了图快捷,使用了全局变量,然后就想到了一些危害//  1.线程不安全:线程中多个全局变量,修改容易冲突,需要加锁//  2.增加耦合性:修改全局变量可能会影响其他模块//  3.难以定位修改:难以定位全局变量在哪里被修改了,加大了调用难度//  4.长期占用内存:生命

    2022年8月21日
    5
  • 二维码生成器小程序_小程序二维码制作

    二维码生成器小程序_小程序二维码制作使用Taro框架写小程序,生成二维码,在微信开放平台找到一个特别好用的二维码生成器(可在原生小程序,mpvue,taro中使用)文档地址:微信开放平台文档地址)github地址:github地址,有详细的描述在taro中使用1、安装npmiwxmp-qrcode2、使用importQRfrom’wxmp-qrcode'<canvasid={this.state…

    2025年6月13日
    4
  • 【转】Smartphone–Android真机管理平台[通俗易懂]

    【转】Smartphone–Android真机管理平台

    2022年3月11日
    45
  • Linux makefile 教程 非常详细 易懂

    Linux makefile 教程 非常详细 易懂最近在学习 Linux 下的 C 编程 买了一本叫 Linux 环境下的 C 编程指南 读到 makefile 就越看越迷糊 可能是我的理解能不行 于是 google 到了以下这篇文章 通俗易懂 然后把它贴出来 方便学习 后记 看完发现这篇文章和 Linux 环境下的 C 编程指南 的 makefile 一章所讲述的惊人的相似 只是这篇文章从一个实例切入 在有些地方比较好理解 能让人看懂就是好文章

    2025年8月10日
    3
  • linux开启网卡fcoe功能,在Redhat上配置FCoE的方法

    linux开启网卡fcoe功能,在Redhat上配置FCoE的方法今天分享一下如何在 REDHAT 下配置 FCOE 第一步 在 redhat 的镜像中 以我用的 redhat6 1 为例 在 packages 文件夹中找到 fcoe utils 1 0 18 2 el6 x86 64 rpm 和 lldpad 0 9 41 4 el6 x86 64 rpm 两个 rmp 包进行安装 这两个安装包的作用一个是安装 LLDP 相关服务因为 dcbx 是基于 LLDP 实现的 这个我在 深度分析数据中心之

    2025年11月11日
    2
  • jsrender

    jsrender

    2022年4月3日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号