数据结构 —— Dijkstra算法

news2024/11/15 8:18:25

数据结构 —— Dijkstra算法

  • Dijkstra算法
  • 划分集合
  • 模拟过程
  • 打印路径

在上次的博客中,我们解决了使用最小的边让各个顶点连通(最小生成树
在这里插入图片描述这次我们要解决的问题是现在有一个图,我们要找到一条路,使得从一个顶点到另一个顶点路径权值之和最小(比如:找到从小潮到胖迪最短的一条路径):
在这里插入图片描述
我们可以看出来,小潮->小傲->胖迪这条路径是最短的。
在这里插入图片描述
而我们今天学的算法,Dijkstra,就是完成这样的工作的:

Dijkstra算法

Dijkstra算法是一种用于寻找图中两个节点之间的最短路径的算法,由荷兰计算机科学家Edsger W. Dijkstra于1956年发明。该算法的基本思想是使用贪心策略,从起始节点开始,逐步扩展到距离它最近的未访问过的节点,直到目标节点被访问。

以下是Dijkstra算法的基本步骤:

  1. 初始化将起点到所有其他节点的距离设为无穷大(表示还未计算),除了起点到自身的距离为0。创建一个空的已访问节点集合和一个包含所有节点的未访问节点集合。
  1. 从未访问节点集合中选择距离起点最近的节点,将其标记为已访问,并更新其邻接节点的距离如果某个邻接节点的距离通过当前节点更短,则更新该邻接节点的距离
  1. 重复步骤2,直到找到目标节点或未访问节点集合为空。
  1. 如果找到了目标节点,则返回从起点到目标节点的最短路径;否则,说明起点和目标节点之间不存在路径。

需要注意的是,Dijkstra算法只适用于没有负权重边的图,因为负权重边会导致算法无法正确地确定最短路径。此外,Dijkstra算法的时间复杂度为O(ElogV),其中E表示边的数量,V表示节点的数量。在实际应用中,可以使用优先队列等数据结构来优化算法的时间复杂度。

我们将上面的图改造复杂一点,这样可以看出Dijkstra算法的高效:
在这里插入图片描述

void TestGraph2()
	{
		string a[] = {"海皇","高斯","小傲","小潮","胖迪","小杨","皖皖"};
		Graph<string, int,INT_MAX, false> g1(a, sizeof(a)/sizeof(a[0]));
		g1.AddEdge("小潮", "小傲", 30);
		g1.AddEdge("小潮", "高斯", 83);
		g1.AddEdge("小潮", "海皇", 34);
		g1.AddEdge("胖迪", "海皇", 78);
		g1.AddEdge("胖迪", "小傲", 76);
		g1.AddEdge("小杨", "皖皖", 54);
		g1.AddEdge("小杨", "高斯", 48);
		g1.AddEdge("高斯", "皖皖", 55);
		g1.AddEdge("胖迪", "高斯", 70);
		g1.AddEdge("小傲", "海皇", 3);

		g1.Print();
		cout << endl;

	}

在这里插入图片描述

划分集合

Dijkstra算法中,提到我们要划分集合一个是访问过的集合,一个是没有被访问过的集合,假设我们从小潮开始:
在这里插入图片描述
我们可以用一个bool的数组,访问过了的标记为true,没有为false。
在这里插入图片描述假设我们要从小潮到胖迪,我们要计算路径之和,我们还需要一个数组存放到各个顶点边的权值:

在这里插入图片描述同时,如果我们想打印路径出来,我们还要一个数组存放路径(这里有点像并查集里面的操作)
在这里插入图片描述

模拟过程

假设我们从小潮开始,各个数组情况如下:
在这里插入图片描述

现在,扫描跟小潮相连的边,最小的权值相关结点标记:
在这里插入图片描述

现在我们从小傲出发,发现海皇近,跳到海皇,发现总路径之和为33,比原来34小,故更新,并标记:

在这里插入图片描述
我们代码实现一下:

    void Dijkstra(const V& srci, vector<W>& dest, vector<int>& parentPath )
    {
        // 将源节点转换为其在顶点列表中的索引
        int srcIndex = FindSrci(srci);

        // 初始化parentPath向量,用于记录最短路径上的前驱节点,初始值为-1表示未访问
        parentPath.resize(_vertex.size(), -1);

        // 初始化dest向量,用于记录从源节点到每个节点的最小距离,初始值为最大权重MAX_W
        dest.resize(_vertex.size(), MAX_W);

        // 给源节点赋值为0,表示从源节点到自身距离为0
        dest[srcIndex] = W();

        // 初始化一个布尔型向量,用于记录每个节点是否已被访问,初始值为false
        vector<bool> isVisted;
        isVisted.resize(_vertex.size(), false);

        // 主循环,迭代次数为顶点数
        for (size_t i = 0; i < _vertex.size(); i++)
        {
            // 初始化最小距离为最大权重MAX_W
            W min = MAX_W;
            size_t u = srcIndex;

            // 寻找未被访问且具有最小dest值的节点u
            for (size_t j = 0; j < _vertex.size(); j++)
            {
                if (isVisted[j] == false && dest[j] < min)
                {
                    min = dest[j];
                    u = j;
                }
            }

            // 标记节点u为已访问
            isVisted[u] = true;

            // 对节点u的所有邻居进行松弛操作
            for (size_t i = 0; i < _vertex.size(); i++)
            {
                // 只处理未被访问的邻居,并且存在从u到i的边(_matrix[u][i] != MAX_W)
                if (isVisted[i] == false && _matrix[u][i] != MAX_W
                    && dest[u] + _matrix[u][i] < dest[i])
                {
                    // 更新从源节点到节点i的最小距离
                    dest[i] = dest[u] + _matrix[u][i];
                    // 更新节点i的前驱节点为u
                    parentPath[i] = u;
                }
            }
        }
    }

在这里插入图片描述

打印路径

打印路径记得一点,最后我们要逆置一下:

    // 打印从源节点到所有其他节点的最短路径
    void PrintShortestPath(const V& src, const vector<W>& dist, const vector<int>& parentPath)
    {
        // 将源节点转换为其在顶点列表中的索引
        size_t srcIndex = FindSrci(src);

        // 遍历所有顶点
        for (size_t i = 0; i < _vertex.size(); i++)
        {
            // 跳过源节点本身
            if (i == srcIndex)
                continue;

            // 创建一个vector,用于存储从目标节点到源节点的路径
            vector<int> path;
            // 当前处理的节点初始化为目标节点
            size_t current = i;

            // 从目标节点出发,回溯到源节点,构建路径
            while (current != srcIndex)
            {
                // 将当前节点添加到路径vector中
                path.push_back(current);
                // 将当前节点设置为其前驱节点,继续回溯
                current = parentPath[current];
            }
            // 最后将源节点添加到路径vector中
            path.push_back(srcIndex);

            // 翻转路径vector,使得路径顺序从源节点到目标节点
            reverse(path.begin(), path.end());

            // 输出路径和对应的最短距离
            for (auto node : path)
            {
                // 输出路径中的每个节点
                cout << _vertex[node] << "->";
            }
            // 输出从源节点到目标节点的最短距离
            cout << dist[i] << endl;
        }
    }

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1910867.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java之数组练习

思路&#xff1a; 代码&#xff1a; public static void main(String[] args) {char[] arrnew char[26];for (char i0;i<arr.length;i ){arr[i] (char) (Ai);}System.out.println(arr);} 结果&#xff1a;

VMware使用技巧

目录 1. 系统快照 1.1 拍摄快照 1.2 查看快照 1.3 应用/删除快照 2. 克隆虚拟机 3. 删除虚拟机 1. 系统快照 1.1 拍摄快照 将当前系统的状态保存下来&#xff0c;如果将来系统出现不可修复的故障&#xff0c;使用快照可以恢复操作系统&#xff1b; CentOS7——拍照—…

【STM32】MDK的编译过程及文件类型全解

1.编译过程简介 编译&#xff1a;MDK软件使用的编译器是armcc和armasm&#xff0c; 它们根据每个c/c和汇编源文件编译成对应的以“.o”为后缀名的对象文件(Object Code&#xff0c;也称目标文件)&#xff0c; 其内容主要是从源文件编译得到的机器码&#xff0c;包含了代码、数据…

Object方法重写

这篇文章大家随意看看就好&#xff0c;只是一点理解的东西&#xff0c;当然你也可以认真调查。 我们需要知道Obecj是java中的一个类&#xff0c;是所有类的父类&#xff0c;即超类。对&#xff0c;超级赛亚人的那个超。 我们需要关注其中的equals、tostring这两个方法。 例如&…

汇川Easy系列PLC使用本地脉冲5轴设置

根据官网手册可以看到&#xff0c;Easy302往上的系列都是支持本地5轴脉冲控制的 常规汇川PLC本地脉冲轴配置时&#xff0c;脉冲和方向的输出点都是成对出现的&#xff0c;但是easy如果要使用5轴的话&#xff0c;就需要自己定义方向 可以看到&#xff0c;Y0,Y1这两个点是单独…

接口测试课程结构

课程大纲 如图&#xff0c;接下来的阶段课程&#xff0c;依次专项讲解如下专题&#xff0c;能力级别为中级&#xff0c;进阶后基本为中高级&#xff1a; 1.接口基础知识&#xff1b; 2.抓包工具&#xff1b; 3.接口工具&#xff1b; 4.mock服务搭建&#xff08;数据模拟服务&am…

国产PLC能否使用无线通讯终端来实现无线通讯?让我们一探究竟

在工业生产车间内&#xff0c;PLC被广泛应用于自动化控制的各个环节。随着智能化工厂的建设&#xff0c;许多PLC仍处于信息孤岛状态&#xff0c;现要将厂区内分散的PLC都建立通讯&#xff0c;如果重新布线工厂量大且不美观&#xff0c;此时就需要用到工业PLC无线通讯设备来解决…

Presto报错:[Presto requires an Oracle or OpenJDK JVM (found Red Hat, Inc.)]

启动前: 已经搭建了jdk环境hadoop的jdk环境配置没有问题 启动Presto时&#xff0c;报错 解决方案: 可能是presto自身变量配置没生效在presto路径下找到bin目录, 进入启动脚本launcher 在 exec "$(dirname “ 0 " ) / l a u n c h e r . p y " " 0"…

守护舌尖安全,破解EHS管理难题,食品加工企业的可持续发展之路

在当今社会&#xff0c;食品安全与环境保护已成为全球关注的热点&#xff0c;食品加工企业作为连接农业与消费者的关键环节&#xff0c;其环境、健康与安全&#xff08;EHS&#xff09;管理水平直接关系到产品的质量和企业的可持续发展。然而&#xff0c;食品加工企业在EHS管理…

面壁智能发布端侧 AI 应用开发平台;快手推出肖像动画技术 LivePortrait丨 RTE 开发者日报

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

C# Winform自制多轴力臂(简单易懂,方便扩展)

WinForms框架广泛应用于上位机开发领域&#xff0c;其中对力臂的精准控制是常见需求之一。本文深入探讨了如何创建自定义的多轴力臂图形控件&#xff0c;不仅涵盖了力臂图形控件的角度调节机制&#xff0c;还详细展示了如何实现力臂运动的生动动态效果&#xff0c;为开发者提供…

AE-时间轴的基础操作

目录 预览&#xff08;快捷键空格&#xff09; 调整时间线显示比例&#xff08;Alt鼠标滚轮&#xff09; 控制预览长度&#xff08;B/N&#xff09; 逐帧移动&#xff08;笔记本&#xff1a;按住fn上下方向键&#xff09; 视频剪切&#xff08;ctrlshiftD&#xff09; 剪…

“El-Table二次封装“这样做【高级前端必备技能之一】

&#x1f525; 前言 这篇文章给大家分享一个高级自定义列表组件从0到1的开发过程&#xff0c;这个列表组件的主要功能有&#xff0c;列表拖拽排序&#xff0c;右侧操作按钮统一使用Tooltip展示&#xff0c;操作表头增加自定列表icon&#xff0c;点击icon可以对列表展示数据进行…

帮企建站包响应式建站源码系统 带完整的安装代码包以及搭建部署教程

系统概述 帮企建站包响应式建站源码系统是一款为企业和个人提供便捷、高效建站解决方案的工具。它融合了先进的技术和设计理念&#xff0c;旨在帮助用户轻松构建具有专业水准的网站&#xff0c;无论在桌面端还是移动端都能呈现出完美的展示效果。 该系统基于响应式设计原则&a…

怎么制作gif动图,视频制作GIF动画更简单

在社交媒体和网络交流中&#xff0c;GIF动画以其生动活泼的表现形式成为了表达情感、幽默和创意的热门媒介。无论是分享日常趣事&#xff0c;还是制作专业演示&#xff0c;一个恰到好处的GIF动图总能吸引目光&#xff0c;传递信息。 但你知道吗&#xff1f;即使没有专业的设计背…

有什么好的录屏软件?分享4款好评的软件!

在数字化时代&#xff0c;录屏软件已成为我们工作、学习和娱乐中不可或缺的工具。但面对市场上琳琅满目的录屏软件&#xff0c;我们该如何选择最适合自己的那一款呢&#xff1f;今天&#xff0c;就让我们一起来揭秘那些备受好评的录屏神器&#xff0c;帮助你轻松找到录屏的首选…

Stable Diffusion——如何把雪碧变成了一个小女孩?

引言 Stable Diffusion WebUI是一个基于深度学习的图像生成工具&#xff0c;它可以将一张图片转换成另一种模样。通过使用先进的稳定扩散算法&#xff0c;这个工具能够生成高质量、高分辨率的图像&#xff0c;同时保持原始图像的核心特征。无论您是想将照片转换成艺术作品&…

7成期刊下降!今年的影响因子为何如此凄惨?

2024年6月20日科睿唯安发布了JCR 2023&#xff0c;21800本期刊最新影响因子正式更新&#xff0c;附完整版EXCEL下载。 影响因子 影响因子&#xff08;Journal Impact Factor&#xff0c;简称JIF或IF&#xff09;是由科睿唯安每年发布的期刊引证报告&#xff08;Journal Citati…

python——list

在Python中&#xff0c;list是一种非常灵活的数据结构&#xff0c;可以用来存储一系列的元素。这些元素可以是任何类型&#xff0c;包括数字、字符串、其他列表等&#xff0c;并且它们不需要是同一种类型。 列表特征&#xff1a; 以下是一些关于Python列表的基本操作&#xff…

书生大模型实战营(暑假场)-入门岛-第一关

书生大模型实战营暑假场重磅开启&#xff01;&#xff0c;这场学习路线看起来很好玩呀&#xff0c;闯关学习既能学到知识又有免费算力可得&#xff0c;太良心啦。感兴趣的小伙伴赶快一起报名学习吧&#xff01;&#xff01;&#xff01; 关卡任务 好的&#xff0c;我们废话不多…