首页 > 编程语言 >【图论】迪杰特斯拉算法

【图论】迪杰特斯拉算法

时间:2024-10-08 21:22:39浏览次数:9  
标签:图论 dist 特斯拉 路径 迪杰 更新 算法 顶点

文章目录

在这里插入图片描述

迪杰特斯拉算法

迪杰特斯拉算法是由荷兰计算机科学家艾兹赫尔·迪杰特斯拉(Edsger W. Dijkstra)在1956年提出的,用于解决单源最短路径问题的经典算法。该算法的目标是从一个起始顶点找到到图中其他顶点的最短路径。

主要特点

  • 适用于带权图,其中权重为非负数。(为什么只适用于非负数,因为迪杰斯特拉的思想是贪心测量,当有负权引入的时候,贪心策略将不再适用)
  • 解决从单个源点到其他所有顶点的最短路径问题。
  • 时间复杂度:当使用优先队列(例如堆)时,复杂度为 O ( E log ⁡ V ) O(E \log V) O(ElogV),其中 V V V 为顶点数量, E E E 为边的数量。

基本思想

Dijkstra算法通过不断探索距离最近的顶点,逐步扩展其最短路径的已知范围,直到找到从源点到所有其他顶点的最短路径。该算法基于贪心策略:每一步选择尚未处理的、距离源点最近的顶点进行扩展。

算法步骤

  1. 初始化

    • 将起始顶点的距离设为0,其余所有顶点的距离设为∞(表示不可达)。
    • 使用一个优先队列(或最小堆)来存储顶点及其当前的最短距离。
  2. 取距离源点最近的顶点,并标记为已处理。

  3. 对于该顶点的每个邻接顶点,更新其最短距离(如果通过当前顶点可以获得更短的路径,则更新距离)。

  4. 重复步骤2和3,直到所有顶点都被处理过,或优先队列为空。

示例

在这里插入图片描述

实现迪杰斯特拉算法

基本步骤

首先假设我们有如下的一个图:
在这里插入图片描述
灰色的点代表起点,我们需要从起点开始算每个点到起点的最短路径。
第一步按照迪杰斯特拉的表述应该将起点到起点的最短路径初始化为0,起点到另外其他点的距离初始化为正无穷。
在这里插入图片描述
这里我们更新完s点之后,应该更新和s点相连的点的最短路径了,由于之前s到t点和到y点的最短路径是正无穷,由于st和sy都小于两个最短路径,所以更新两个最短路径。
在这里插入图片描述
根据贪心策略,更新出来的两个最短路径,sy更小,所以我们应该更新y相连的路径。
在这里插入图片描述
所以接下来我们应该更新y连接的点的最短路径。
在这里插入图片描述
由于原本s到t的最短路径是10,但是现在的最短路径更新了之后是8,所以更新结果,由于之前s到x的最短路径是正无穷,所以现在将最短路径更新为14,s到z 也是相同的,因为之前的最短路径是正无穷,所以现在将最短路径更新为7.
在这三条最短路径中选择最短的那条:
在这里插入图片描述
这里就应该以z为新的起点
在这里插入图片描述
更新z连接的顶点,z一共有两条边,一条是zs,一条是zx,由于s到s是最近的0,所以这里不需要更新,由于之前s到x的距离是14,所以这里更新s到x的距离。
接下来再从剩下的边中,选择最小的路径。
在这里插入图片描述
从t点开始只有一条路径,所以这里t到x,tx是1,由于之前的st的最短路径是8,所以此时的最短路径是9,9<13所以这里应该更新最短路径为9
在这里插入图片描述
这里最短路径算是更新完了。

算法思路

由于这里我们涉及到最短路径,所以应该开辟一个dist数组,我们来想一想一个dist数组是否能解决问题,很显然是不能的,我们还需要一个数组,记录当前最短路径的前一个顶点的下标,在遍历的时候我们可以索引每一个顶点了。
代码展示:

void Dijkstra(const V& src, vector<W>& dist, vector<int>& pPath)
{
	//获取起点的下标
	size_t srci = GetVertexIndex(src);
	//确定节点的数量
	size_t n = _vertexs.size();
	dist.resize(n, MAX_W);
	pPath.resize(n, MAX_W);

	//自己到自己的距离是0
	dist[srci] = 0;
	//自己的前一个是自己
	pPath[srci] = srci;
	//已经确定最短路径的顶点的集合
	vector<bool> S(n, false);
	for(size_t j=0;j<n;j++)
	{
		//选择最短路径顶点且不在s中更新其他路径
		int u = 0;     //最小的那个点
		W min = MAX_W; //最小权值
		for (size_t i = 0;i < n;i++)
		{
			if (S[i] == false && dist[i] < min)
			{
				//选出最小的点
				u = i;
				//更新最小权值
				min = dist[i];
			}
		}

		//u被选出来
		S[u] = true;
		//松弛更新u连接出去的顶点v    srci->u   u->v
		for (size_t v = 0;v < n;v++)
		{
			//确定u连接出去的所有边
			if (S[v] == false && _matrix[u][v] != MAX_W && (dist[u] + _matrix[u][v]) < dist[v])
			{
				dist[v] = dist[u] + _matrix[u][v];
				//将v的父亲更新为u
				pPath[v] = u;
			}
		}
	}
}

打印路径节点和最短路径:

//打印最短路径
void PrinrtShotPath(const V& src, vector<W>& dist, vector<int>& pPath)
{
	//获取起点的下标
	size_t srci = GetVertexIndex(src);
	//确定节点的数量
	size_t n = _vertexs.size();
	for (size_t i = 0;i < n;i++)
	{
		if (i != srci)
		{
			// 先找出i顶点的路径
			vector<int> path;
			size_t parenti = i;
			//先将自己存进去(自己不是原点先push进去)
			while (parenti != srci)
			{
				path.push_back(parenti);
				parenti = pPath[parenti];
			}
			path.push_back(srci);
			//将路径逆置
			reverse(path.begin(), path.end());
			//打印出路径
			for (auto e : path)
			{
				cout << _vertexs[e] << "->";
			}
			//打印最短路径
			cout << dist[i];
			cout << endl;
		}
	}
}

因为根据最后一个节点去推上一个节点,推完之后数组中的节点会是一个反着的路径,所以在打印的时候,应该先把数组逆置,逆置之后再进行打印。

总结

在本文中,我们深入探讨了迪杰斯特拉算法的原理与应用。作为一种经典的最短路径算法,迪杰斯特拉算法通过优先队列有效地解决了从单一源点到其他所有节点的最短路径问题。我们分析了其时间复杂度和空间复杂度,了解了在不同图形结构下的性能表现。

通过示例和实现,我们不仅掌握了算法的基本步骤,还体验了其在实际应用中的重要性。无论是在交通导航、网络路由还是各种优化问题中,迪杰斯特拉算法都发挥着不可或缺的作用。

希望本文能够帮助你更好地理解迪杰斯特拉算法,并为你在图论和算法领域的进一步学习打下坚实的基础。如果你有任何疑问或想法,欢迎在评论区与我交流!

标签:图论,dist,特斯拉,路径,迪杰,更新,算法,顶点
From: https://blog.csdn.net/2301_79969994/article/details/142767235

相关文章

  • CF547D Mike and Fish(图论建模)
    题意二维平面上有\(n\)个点\((x_i,y_i)\),你需要给每个点染色红色或蓝色使得每一行、每一列上红蓝点数差小于等于1。\(n,x_i,y_i\le2\times10^5\)。分析方法一:上下界网络流对所有行和列建点,\(x_i\rightarrowy_i\)连边,流量\([0,1]\),有流量表示染红。源点向行点连边,流量......
  • Day44~45 图论回顾
    P6628[省选联考2020B卷]丁香之路枚举每个终点,先向\(s\)额外加一条边,就等价于求最小的欧拉回路。(根据图的性质,不走重复路一定更优)刚开始的\(m\)条边必定会组成一系列的连通块,我们还要加边使之联通。又要满足无向图欧拉回路的性质。也就是每个点的度数为偶数。你考虑直......
  • 图论
    原来我没学过图论。尝试把普及组+提高组的大部分图论内容重学。定义啥的不写了。OI-Wiki有详细的。图的存储一般来说有3种存图方法:直接存。例如structEdge{inta,b,w;}edges[N];。邻接矩阵。即一个矩阵\(g\),其中\(g_{i,j}\)表示\(i,j\)间的边数。如果......
  • 图论相关
    图论树LCA性质\(LCA(A\cupB)=LCA(LCA(A),LCA(B))\)一堆点集的LCA等于其中dfn最大的和最小的点的LCAdfs序求lca好写且\(O(1)\),吊打欧拉序和倍增。如果两个点\(x\)和\(y\)不存在祖孙关系,那么\(LCA(x,y)=fa(min(dfn_x,dfn_y))\)。我们钦定\(dfn_x<......
  • 算法题之图论 [NOIP2001 提高组] Car的旅行路线详细题解
    P1027[NOIP2001提高组]Car的旅行路线这道题的思路呢,就是建个图,然后跑一遍Floyd,比较最小值就可以解决了。but!它每个城市只给三个点(共四个),所以还得计算出第四个点坐标。这里根据矩形的中点公式来表示未知点的坐标:(这个思路源于大佬 _jimmywang_       ......
  • 多智能体协同控制(2):代数图论
    在上一节中,提到了分布式一致性算法的实现与多智能体之间的交流方式密切相关。这一节用图论来揭示不同多智能体之间交流方式的本质差异。图的基本定义我们可以将不同智能体之间的通信方式,抽象出来,称为“通信图”(graph)。如右图所示,舍弃物理意义,将每个智能体抽象成节点(vertex)1,......
  • 图论指南
    前置知识在了解图论之前,还需要知道怎么存图。vector用vector<int>G[MAXN]来存图。$G_i$表示从$i$出发,能够到达的点的数组。空间开销相较于链式前向星较大。也可以将vector替换为其他STL容器,如list、unordered_set、deque等。list的写法空间更优,常数较小,但是vecto......
  • 图论进阶学习笔记(三)(2024.8.12)
    二分图定义如果你能把一个图划分成两个集合,集合内部的点没有边相连接,那么这个图就是一个二分图,如图就是一个二分图:交错路:从一个没有被匹配的点出发,依次走非匹配边,匹配边,非匹配边……最后到达另外一部点当中某个没有被匹配的点的路径。增广路:从一个没有被匹配的点出发,依次走......
  • 图论进阶学习笔记(二)(2024.8.1)
    图的连通性强连通分量割点缩点例题一边双连通分量点双连通分量2-SAT例题二例题三欧拉回路例题四......
  • 认知神经科学分析指标——图论指标之全局集群系数
    图论指标在认知神经科学或脑科学的研究中,通常作为研究脑网络表现的描述性指标之一,而图论指标从全局性来分可以分为:节点指标和全局指标,而根据描述脑网络整合性表现又可分为:整合指标和分离指标。该随笔主要涉及图论指标中全局指标及整合指标的全局集群系数,英文全称为GlobalCluster......