当前位置: 首页 > news >正文

DS图(下)(19)

文章目录

  • 前言
  • 一、最短路径的概念
  • 二、单源最短路径-Dijkstra算法
  • 三、单源最短路径-Bellman-Ford算法
  • 四、多源最短路径-Floyd-Warshall算法
  • 总结


前言

  加油,今天就是图的最后一篇了,撑住!!
  今天我们要学的就是最短路径问题!!


一、最短路径的概念

  • 最短路径问题:从带权有向图中的某一顶点出发,找出一条通往另一顶点的最短路径,最短指的是路径各边的权值总和达到最小,最短路径可分为单源最短路径和多源最短路径。

  • 单源最短路径指的是从图中某一顶点出发,找出通往其他所有顶点的最短路径,而多源最短路径指的是,找出图中任意两个顶点之间的最短路径。

二、单源最短路径-Dijkstra算法

有一个很重要的使用前提是:所有边的权值非负

Dijkstra算法的基本思想如下:

  1. 将图中的顶点分为两个集合,集合 S 中的顶点是已经确定从源顶点到该顶点的最短路径的顶点,集合 Q 中的顶点是尚未确定从源顶点到该顶点的最短路径的顶点。

  2. 每个顶点都有一个估计值,表示从源顶点到该顶点的可能最短路径长度,每次从集合 Q 中选出一个估计值最小的顶点,将其加入到集合 S 中,并对该顶点连接出去的顶点的估计值和前驱顶点进行松弛更新。

  3. 按照上述步骤不断从集合 Q 中选取估计值最小的顶点到集合 S 中,直到所有的顶点都被加入到集合 S 中,此时通过各个顶点的估计值就可以得知源顶点到该顶点的最短路径长度,通过各个顶点的前驱顶点就可以得知最短路径的走向。

在这里插入图片描述
Dijkstra算法的实现:

  1. 使用一个 dist 数组来记录从源顶点到各个顶点的最短路径长度估计值,初始时将源顶点的估计值设置为权值的缺省值(比如int就是0),表示从源顶点到源顶点的路径长度为0,将其余顶点的估计值设置为 MAX_W ,表示从源顶点暂时无法到达其他顶点。

  2. 使用一个 parentPath 数组来记录到达各个顶点路径的前驱顶点,初始时将各个顶点的前驱顶点初始化为 -1 ,表示各个顶点暂时只能自己到达自己,没有前驱顶点。

  3. 使用一个 bool 数组来记录各个顶点是否在 S 集合中,初始时所有顶点均不在 S 集合,表示各个顶点都还没有确定最短路径。

  4. 每次从 Q 集合中选出一个估计值最小的顶点 u,将其加入到 S 集合,并对顶点 u 连接出去的各个顶点 v 进行松弛更新,如果能够将顶点 v 更新出更小的估计值,则更新其估计值,并将被更新的顶点 v 的前驱顶点改为顶点 u ,因为从顶点 u 到顶点 v 能够得到更小的估计值,所以在当前看来(后续可能还会更新)到达顶点 v 的最短路径的前驱顶点就应该是顶点 u ,如果不能将顶点 v 更新出更小的估计值,则维持原样。

  5. 当所有的顶点都加入集合 S 后,dist 数组中存储的就是从源顶点到各个顶点的最短路径长度,parentPath 数组中存储的就是从源顶点到各个顶点的最短路径的前驱顶点,通过不断查找各个顶点的前驱顶点,最终就能得到从源顶点到各个顶点的最短路径。

		void PrintShortPath(const V& src, const vector<W>& dist, const 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;while (parenti != srci){path.push_back(parenti);parenti = pPath[parenti];}path.push_back(srci);reverse(path.begin(), path.end());for (auto index : path){cout << _vertexs[index] << "->";}cout << "权值和:" <<dist[i] << endl;}}}// 顶点个数是N  -> 时间复杂度:O(N^2)空间复杂度:O(N)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, -1);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];}}S[u] = true;// 松弛更新u连接顶点v  srci->u + u->v <  srci->v  更新for (size_t v = 0; v < n; ++v){if (S[v] == false && _matrix[u][v] != MAX_W&& dist[u] + _matrix[u][v] < dist[v]){dist[v] = dist[u] + _matrix[u][v];pPath[v] = u;}}}}
  1. 为了方便观察,可以在类中增加一个 PathprintShortPath 接口,用于根据 dist 和 parentPath 数组来打印最短路径及路径权值。
  2. 对于从源顶点 s 到目标顶点 j 的最短路径来说,如果最短路径经过了顶点 i ,那么最短路径中从源顶点 s 到顶点 i 的这条子路径一定是源顶点 s 到顶点 i 的最短路径,因此可以通过存储前驱顶点的方式来表示从源顶点到各个顶点的最短路径。
  3. Dijkstra算法每次需要选出一个顶点,并对其连接出去的顶点进行松弛更新,因此其时间复杂度是 O ( N^2 ) 空间复杂度是 O (N) 。

Dijkstra算法的原理

  1. Dijkstra算法每次从集合 Q 中选出一个估计值最小的顶点 u ,将该顶点加入到集合 S 中,表示确定了从源顶点到顶点 u 的最短路径。

  2. 因为图中所有边的权值非负(使用Dijkstra算法的前提),所以对于估计值最小的顶点 u 来说,其估计值不可能再被其他比它估计值更大的顶点松弛更新得更小,因此顶点 u 的最短路径就是当前的估计值。

  3. 而对于集合 Q 中的其他顶点来说,这些顶点的估计值比顶点 u 的估计值大,因此顶点 u 可能将它们的估计值松弛更新得更小,所以顶点 u 在加入集合 S 后还需要尝试对其连接出去的顶点进行松弛更新。

三、单源最短路径-Bellman-Ford算法

跟前者相比可以处理负权的边,但是本质上是暴力求解,效率不如 Dijkstra

Bellman-Ford算法的基本思想如下:

  1. Bellman-Ford算法本质是暴力求解,对于从源顶点 s 到目标顶点 j 的路径来说,如果存在从源顶点 s 到顶点 i 的路径,还存在一条从顶点 i 到顶点 j 的边,并且其权值之和小于当前从源顶点 s 到目标顶点 j 的路径长度,则可以对顶点 j 的估计值和前驱顶点进行松弛更新。

  2. Bellman-Ford算法根据路径的终边来进行松弛更新,但是仅对图中的边进行一次遍历可能并不能正确更新出最短路径,最坏的情况下需要对图中的边进行 n−1 轮遍历( n 表示图中的顶点个数)

Bellman-Ford算法的实现:

  • 使用一个 dist 数组来记录从源顶点到各个顶点的最短路径长度估计值,初始时将源顶点的估计值设置为权值的缺省值(比如int就是0),表示从源顶点到源顶点的路径长度为0,将其余顶点的估计值设置为 MAX_W ,表示从源顶点暂时无法到达其他顶点。

  • 使用一个 parentPath 数组来记录到达各个顶点路径的前驱顶点,初始时将各个顶点的前驱顶点初始化为 -1 ,表示各个顶点暂时只能自己到达自己,没有前驱顶点。

  • 对图中的边进行 n−1 轮遍历,对于 i−>j 的边来说,如果存在 s−>i 的路径,并且 s−>i 的路径权值与边 i−>j 的权值之和小于当前 s−>j 的路径长度,则将顶点 j 的估计值进行更新,并将顶点 j 的前驱顶点改为顶点 i ,因为 i−>j 是图中的一条直接相连的边,在这条路径中顶点 j 的上一个顶点就是顶点 i 。

  • 再对图中的边进行一次遍历,尝试进行松弛更新,如果还能更新则说明图中带有负权回路,无法找到最短路径。

		// 时间复杂度:O(N^3) 空间复杂度:O(N)bool BellmanFord(const V& src, vector<W>& dist, vector<int>& pPath){size_t n = _vertexs.size();size_t srci = GetVertexIndex(src);// vector<W> dist,记录srci-其他顶点最短路径权值数组dist.resize(n, MAX_W);// vector<int> pPath 记录 srci-其他顶点 最短路径父顶点数组pPath.resize(n, -1);// 先更新 srci -> srci 为缺省值dist[srci] = W();//cout << "更新边:i->j" << endl;// 总体最多更新n轮// 其实 n - 1 就行了for (size_t k = 0; k < n; ++k){// i->j 更新松弛bool update = false;cout << "更新第:" << k << "轮" << endl;for (size_t i = 0; i < n; ++i){for (size_t j = 0; j < n; ++j){// srci -> i + i ->jif (_matrix[i][j] != MAX_W && dist[i] + _matrix[i][j] < dist[j]){update = true;cout << _vertexs[i] << "->" << _vertexs[j] << ":" << _matrix[i][j] << endl;dist[j] = dist[i] + _matrix[i][j];pPath[j] = i;}}}// 如果这个轮次中没有更新出更短路径,那么后续轮次就不需要再走了if (update == false){break;}}// 还能更新就是带负权回路for (size_t i = 0; i < n; ++i){for (size_t j = 0; j < n; ++j){// srci -> i + i ->jif (_matrix[i][j] != MAX_W && dist[i] + _matrix[i][j] < dist[j]){return false;}}}return true;}

贝尔曼算法的原理

  • 每一轮贝尔曼 - 福特算法会对图中的所有边进行一次松弛操作。在第一轮松弛操作中,算法可以找到从源点出发经过最多 1 条边到达各个顶点的最短路径;在第二轮松弛操作中,算法可以找到从源点出发经过最多 2 条边到达各个顶点的最短路径;以此类推。
  • 由于任意两个顶点之间的最短路径最多包含 N - 1 条边,所以最多经过 N - 1 轮松弛操作,就可以找到从源点到各个顶点的最短路径。也就是说,在 N - 1 轮之后,所有顶点的最短路径估计值都不会再发生变化。
  • 如果形成回路的各个边的权值之和为负数,则该回路为负权回路,找不到最短路径。
  • 如果形成回路的各个边的权值之和为非负数,则多走这个回路是“徒劳”的,可能会使得路径长度变长

Bellman-Ford算法还有一个优化方案叫做SPFA(Shortest Path Faster Algorithm),就交给大家自行了解了

四、多源最短路径-Floyd-Warshall算法

Floyd-Warshall算法的基本思想如下:

  1. Floyd-Warshall算法解决的是任意两点间的最短路径的算法,其考虑的是路径的中间顶点,对于从顶点 i 到顶点 j 的路径来说,如果存在从顶点 i 到顶点 k 的路径,还存在从顶点 k 到顶点 j 的路径,并且这两条路径的权值之和小于当前从顶点 i 到顶点 j 的路径长度,则可以对顶点 j 的估计值和前驱顶点进行松弛更新。

  2. Floyd-Warshall算法本质是一个简单的动态规划,就是判断从顶点 i 到顶点 j 的这条路径是否经过顶点 k ,如果经过顶点 k 可以让这条路径的权值变得更小,则经过,否则则不经过。

Floyd-Warshall算法的实现:

  • 使用一个 vvDist 二维数组来记录从各个源顶点到各个顶点的最短路径长度的估计值,vvDist[i][j] 表示从顶点 i 到顶点 j 的最短路径长度的估计值,初始时将二维数组中的值全部初始化为 MAX_W ,表示各个顶点之间暂时无法互通。

  • 使用一个 vvParentPath 二维数组来记录从各个源顶点到达各个顶点路径的前驱顶点,初始时将二维数组中的值全部初始化为-1,表示各个顶点暂时只能自己到自己,没有前驱顶点。

  • 根据邻接矩阵对 vvDist 和 vvParentPath 进行初始化,如果从顶点 i 到顶点 j 有直接相连的边,则将 vvDist[i][j] 初始化为这条边的权值,并将 vvParentPath[i][j] 初始化为 i ,表示在 i−>j 这条路径中顶点 j 前驱顶点是 i ,将 vvDist[i][i] 的值设置为权值的缺省值(比如int就是0),表示自己到自己的路径长度为0。

  • 依次取各个顶点 k 作为 i−>j 路径的中间顶点,如果同时存在 i−>k 的路径和 k−>j 的路径,并且这两条路径的权值之和小于当前 i−>j 路径的权值,则更新 vvDist[i][j] 的值,并将 vvParentPath[i][j] 的值更新为 vvParentPath[k][j] 的值。

		void FloydWarshall(vector<vector<W>>& vvDist, vector<vector<int>>& vvpPath){size_t n = _vertexs.size();vvDist.resize(n);vvpPath.resize(n);// 初始化权值和路径矩阵for (size_t i = 0; i < n; ++i){vvDist[i].resize(n, MAX_W);vvpPath[i].resize(n, -1);}// 直接相连的边更新一下for (size_t i = 0; i < n; ++i){for (size_t j = 0; j < n; ++j){if (_matrix[i][j] != MAX_W){vvDist[i][j] = _matrix[i][j];vvpPath[i][j] = i;}if (i == j){vvDist[i][j] = W();}}}// abcdef  a {} f ||  b {} c// 最短路径的更新 i -> {其他顶点} -> jfor (size_t k = 0; k < n; ++k){for (size_t i = 0; i < n; ++i){for (size_t j = 0; j < n; ++j){// k 作为的中间点尝试去更新i->j的路径if (vvDist[i][k] != MAX_W && vvDist[k][j] != MAX_W&& vvDist[i][k] + vvDist[k][j] < vvDist[i][j]){vvDist[i][j] = vvDist[i][k] + vvDist[k][j];// 找跟j相连的上一个邻接顶点// 如果k->j 直接相连,上一个点就k,vvpPath[k][j]存就是k// 如果k->j 没有直接相连,k->...->x->j,vvpPath[k][j]存就是xvvpPath[i][j] = vvpPath[k][j];}}}}

  Floyd-Warshall算法的时间复杂度是 O ( N^2 ),空间复杂度是 O ( N^2 ) 。虽然求解多源最短路径也可以以图中不同的顶点作为源顶点,去调用Dijkstra算法或Bellman-Ford算法,但Dijkstra算法不能解决带负权的图,Bellman-Ford算法调用 N 次的时间复杂度又太高


总结

  结束了,感觉如何,难吧!!!
  不用怀疑自己,我觉得这确实是最难的一部分,甚至比红黑树还难理解,因为它太抽象了

相关文章:

DS图(下)(19)

文章目录 前言一、最短路径的概念二、单源最短路径-Dijkstra算法三、单源最短路径-Bellman-Ford算法四、多源最短路径-Floyd-Warshall算法总结 前言 加油&#xff0c;今天就是图的最后一篇了&#xff0c;撑住&#xff01;&#xff01;   今天我们要学的就是最短路径问题&…...

鸿蒙Harmony-Progress组件概述

鸿蒙Harmony-Progress组件概述 1.1Progress组件概述 作用&#xff1a;显示操作或任务的进度&#xff0c;支持线性&#xff0c;环形&#xff0c;刻度等多种样式适用场景&#xff1a;文件上传/下载、任务完成度、系统状态反馈等 2.1基础属性&#xff08;参考官方文档&#xff…...

流数据库中的RisingWave和Materialize

流数据库&#xff08;Streaming Database&#xff09;是一种专门设计用于处理大量实时流数据的数据库&#xff0c;它能够在数据生成时立即进行处理&#xff0c;从而实现实时洞察和分析。RisingWave和Materialize都是这一领域的代表性技术。RisingWave和Materialize都是强大的流…...

【C++】多态详细讲解

本篇来聊聊C面向对象的第三大特性-多态。 1.多态的概念 多态通俗来说就是多种形态。多态分为编译时多态(静态多态)和运⾏时多态(动态多态)。 编译时多态&#xff1a;主要就是我们前⾯讲的函数重载和函数模板&#xff0c;他们传不同类型的参数就可以调⽤不同的函数&#xff0c;通…...

防火墙的安全策略

1.VLAN 2属于办公区;VLAN 3属于生产区&#xff0c;创建时间段 [FW]ip address-set BG type object [FW-object-address-set-BG]address 192.168.1.0 mask 25 [FW]ip address-set SC type object [FW-object-address-set-SC]address 192.168.1.129 mask 25 [FW]ip address-se…...

Android 进程间通信

什么是IPC&#xff1f; Android 进程间通信&#xff08;IPC&#xff0c;Inter-Process Communication&#xff09;是Android操作系统中不同进程间交换数据和资源的一种机制。由于Android是多任务操作系统&#xff0c;每个应用通常运行在自己的进程中&#xff0c;以提高安全性和…...

【优先算法】专题——位运算

在讲解位运算之前我们来总结一下常见的位运算 一、常见的位运算 1.基础为运算 << &&#xff1a;有0就是0 >> |&#xff1a;有1就是1 ~ ^&#xff1a;相同为0&#xff0c;相异位1 /无进位相加 2.给一个数 n&#xff0c;确定它的二进制表示…...

深入理解k8s中的容器存储接口(CSI)

CSI出现的原因 K8s原生支持一些存储类型的PV&#xff0c;像iSCSI、NFS等。但这种方式让K8s代码与三方存储厂商代码紧密相连&#xff0c;带来不少麻烦。比如更改存储代码就得更新K8s组件&#xff0c;成本高&#xff1b;存储代码的bug还会影响K8s稳定性&#xff1b;K8s社区维护和…...

ZZNUOJ(C/C++)基础练习1061——1070(详解版)

目录 1061 : 顺序输出各位数字 C语言版 C版 1062 : 最大公约数 C C 1063 : 最大公约与最小公倍 C C 1064 : 加密字符 C C 1065 : 统计数字字符的个数 C C 1066 : 字符分类统计 C C 1067 : 有问题的里程表 C C 1068 : 进制转换 C C C&#xff08;容器stack…...

ES6 变量解构赋值总结

1. 数组的解构赋值 1.1 基本用法 // 基本数组解构 const [a, b, c] [1, 2, 3]; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3// 跳过某些值 const [x, , y] [1, 2, 3]; console.log(x); // 1 console.log(y); // 3// 解构剩余元素 const [first, ...re…...

机理模型与数据模型融合的方式

机理模型与数据模型的融合旨在结合两者的优势&#xff0c;以提供更准确、可靠的预测和决策支持。以下是几种常见的融合方式及其示例&#xff1a; 1. 特征增强&#xff08;Feature Augmentation&#xff09; 描述&#xff1a;将由机理模型计算得到的结果作为额外特征加入到数据…...

高效 MyBatis SQL 写法一

高效 MyBatis SQL 写法一 前言 MyBatis 作为一款优秀的持久层框架&#xff0c;极大地简化了数据库操作。 然而&#xff0c;在实际开发中&#xff0c;XML 配置的编写仍然可能显得繁琐。 本文将分享一些 MyBatis 动态 SQL 的优质写法&#xff0c;帮助开发者提升效率并减少错误…...

vue3中的ref相关的api及用法

在 Vue 3 中&#xff0c;ref 相关的 API 主要用于管理响应式数据。以下是 ref 相关的 API 及其用法&#xff1a; 1. ref ref 用于创建响应式的基本数据类型或对象。 用法示例&#xff1a; <script setup> import { ref } from vue;const count ref(0);const incremen…...

3 卷积神经网络CNN

1 Image Classification (Neuron Version) – 1.1 Observation 1 1.2 Observation 2 如果不同的receptive field需要相同功能的neuron&#xff0c;可以使这些neuron共享参数 1.3 Benefit of Convolutional Layer 2 Image Classification (Filter Version) 不用担心filter大小…...

CSV数据分析智能工具(基于OpenAI API和streamlit)

utils.py&#xff1a; from langchain_openai import ChatOpenAI from langchain_experimental.agents.agent_toolkits import create_csv_agent import jsonPROMPT_TEMPLATE """你是一位数据分析助手&#xff0c;你的回应内容取决于用户的请求内容。1. 对于文…...

解决php8.3无法加载curl扩展

把它的值更改为扩展存在的目录的绝对路径(扩展存在的目录为有php_xxx.dll存在的目录) extension_dir "e:\serv\php83\ext" 然后从php根目录复制 libssh2.dll 和 libcrypto-*.dll 和 libssl-*.dll 到Apache根目录下的bin目录 重启apache服务即可...

拍照对比,X70 PRO与X90 PRO+的细节差异

以下是局部截图&#xff08;上X70P下X90PP&#xff09; 对比1 这里看不出差异。 对比2 X90PP的字明显更清楚。 对比3 中下的字&#xff0c;X90PP显然更清楚。...

《MPRnet》学习笔记

paper&#xff1a;2102.02808 GitHub&#xff1a;swz30/MPRNet: [CVPR 2021] Multi-Stage Progressive Image Restoration. SOTA results for Image deblurring, deraining, and denoising. 目录 摘要 1、介绍 2、相关工作 2.1 单阶段方法 2.2 多阶段方法 2.3 注意力机…...

机器学习-线性回归(参数估计之结构风险最小化)

前面我们已经了解过关于机器学习中的结构风险最小化准则&#xff0c;包括L1 正则化&#xff08;Lasso&#xff09;、L2 正则化&#xff08;Ridge&#xff09;、Elastic Net&#xff0c;现在我们结合线性回归的场景&#xff0c;来了解一下线性回归的结构风险最小化&#xff0c;通…...

C++11详解(二) -- 引用折叠和完美转发

文章目录 2. 右值引用和移动语义2.6 类型分类&#xff08;实践中没什么用&#xff09;2.7 引用折叠2.8 完美转发2.9 引用折叠和完美转发的实例 2. 右值引用和移动语义 2.6 类型分类&#xff08;实践中没什么用&#xff09; C11以后&#xff0c;进一步对类型进行了划分&#x…...

深度学习系列--01.入门

一.深度学习概念 深度学习&#xff08;Deep Learning&#xff09;是机器学习的分支&#xff0c;是指使用多层的神经网络进行机器学习的一种手法抖音百科。它学习样本数据的内在规律和表示层次&#xff0c;最终目标是让机器能够像人一样具有分析学习能力&#xff0c;能够识别文字…...

熵采样在分类任务中的应用

熵采样在分类任务中的应用 在机器学习的分类任务里,数据的标注成本常常制约着模型性能的提升。主动学习中的熵采样策略,为解决这一难题提供了新的思路。本文将带你深入了解熵采样在分类任务中的原理、应用及优势。 一、熵采样的原理(优化版) 熵,源于信息论,是对不确定…...

vite配置之---依赖优化选项

vite optimizeDeps 配置项主要在 开发环境 中对依赖项发挥作用 optimizeDeps.entries vite optimizeDeps.entries 是 Vite 配置中的一个选项&#xff0c;用来指定要优化的入口文件。这在开发环境中尤其有用&#xff0c;因为它告诉 Vite 需要预构建哪些文件&#xff0c;以便加速…...

Shell基础:中括号的使用

在Shell脚本中&#xff0c;中括号&#xff08;[ ... ] 和 [[ ... ]]&#xff09;是一种常见的条件测试结构。它们用于进行文件类型检查、值比较以及逻辑判断。通过了解它们的不同特点和用法&#xff0c;能够帮助你编写更加高效、安全且易读的脚本。本文将详细介绍Shell中单中括…...

oracle ORA-27054报错处理

现象 在oracle执行expdp&#xff0c;rman备份&#xff0c;xtts的时候,由于没有足够的本地空间&#xff0c;只能使用到NFS的文件系统但有时候会出现如下报错 ORA-27054: NFS file system where the file is created or resides is not mounted with correct options根据提示信…...

SpringCloud速通教程

视频地址 文档地址 3. SpringCloud - 快速通关...

MapReduce分区

目录 1. MapReduce分区1.1 哈希分区1.2 自定义分区 2. 成绩分组2.1 Map2.2 Partition2.3 Reduce 3. 代码和结果3.1 pom.xml中依赖配置3.2 工具类util3.3 GroupScores3.4 结果 参考 本文引用的Apache Hadoop源代码基于Apache许可证 2.0&#xff0c;详情请参阅 Apache许可证2.0。…...

python算法和数据结构刷题[3]:哈希表、滑动窗口、双指针、回溯算法、贪心算法

回溯算法 「所有可能的结果」&#xff0c;而不是「结果的个数」&#xff0c;一般情况下&#xff0c;我们就知道需要暴力搜索所有的可行解了&#xff0c;可以用「回溯法」。 回溯算法关键在于:不合适就退回上一步。在回溯算法中&#xff0c;递归用于深入到所有可能的分支&…...

JDK 中 NIO 框架设计与实现:深入剖析及实战样例

一、引言 在 Java 的发展历程中&#xff0c;I/O&#xff08;Input/Output&#xff09;操作一直是构建高效、稳定应用程序的关键环节。传统的 Java I/O 操作基于流&#xff08;Stream&#xff09;的方式&#xff0c;虽然简单易用&#xff0c;但在面对高并发、大规模数据传输等场…...

基于springboot校园点歌系统

基于Spring Boot的校园点歌系统是一种专为校园场景设计的音乐点播平台&#xff0c;它能够丰富学生的校园生活&#xff0c;提升学生的娱乐体验。以下是对该系统的详细介绍&#xff1a; 一、系统背景与意义 在校园环境中&#xff0c;学生们对于音乐有着浓厚的兴趣&#xff0c;传…...

Spring 核心技术解析【纯干货版】- IX:Spring 数据访问模块 Spring-Jdbc 模块精讲

在现代企业级应用中&#xff0c;数据访问层的稳定性和高效性至关重要。为了简化和优化数据库操作&#xff0c;Spring Framework 提供了 Spring-JDBC 模块&#xff0c;旨在通过高度封装的 JDBC 操作&#xff0c;简化开发者的编码负担&#xff0c;减少冗余代码&#xff0c;同时提…...

React开发中箭头函数返回值陷阱的深度解析

React开发中箭头函数返回值陷阱的深度解析 一、箭头函数的隐式返回机制&#xff1a;简洁背后的规则二、块函数体中的显式返回要求&#xff1a;容易被忽视的细节三、真实场景下的案例分析案例1&#xff1a;忘记return导致组件渲染失败案例2&#xff1a;异步操作中的返回值陷阱 四…...

线程同步时定义 std::mutex 为什么要在前面添加 mutable 关键字

在C中&#xff0c;mutable关键字用于修饰类的成员变量&#xff0c;表示即使在一个const对象中&#xff0c;该成员变量也可以被修改。对于mutex这样的同步原语&#xff0c;使用mutable是必要的&#xff0c;原因如下&#xff1a; 1. 为什么需要 mutable&#xff1f; mutex通常用…...

【多线程】线程池核心数到底如何配置?

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 前置回顾2. 动态线程池2.1 JMX 的介绍2.1.1 MBeans 介绍 2.2 使用 JMX jconsole 实现动态修改线程池2.2.…...

Linux find 命令 | grep 命令 | 查找 / 列出文件或目录路径 | 示例

注&#xff1a;本文为 “Linux find 命令 | grep 命令使用” 相关文章合辑。 未整理去重。 如何在 Linux 中查找文件 作者&#xff1a; Lewis Cowles 译者&#xff1a; LCTT geekpi | 2018-04-28 07:09 使用简单的命令在 Linux 下基于类型、内容等快速查找文件。 如果你是 W…...

爬楼梯(dp)杭电复试

一个楼梯共有 nn 级台阶&#xff0c;每次可以走一级或者两级或者三级&#xff0c;问从第 00 级台阶走到第 nn 级台阶一共有多少种方案。 输入格式 一个整数 NN。 输出格式 一个整数&#xff0c;表示方案总数。 数据范围 1≤N≤201≤N≤20 输入样例&#xff1a; 4输出样…...

JVM执行引擎

一、执行引擎的概述: 执行引擎是]ava虚拟机核心的组成部分之一; “虚拟机”是一个相对于“物理机”的概念&#xff0c;这两种机器都有代码执行能力&#xff0c;其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的&#xff0c;而虚拟机的执行引擎则…...

企业四要素如何用PHP进行调用

一、什么是企业四要素&#xff1f; 企业四要素接口是在企业三要素&#xff08;企业名称、统一社会信用代码、法定代表人姓名&#xff09;的基础上&#xff0c;增加了一个关键要素&#xff0c;通常是企业注册号或企业银行账户信息。这种接口主要用于更全面的企业信息验证&#x…...

基于springboot河南省旅游管理系统

基于Spring Boot的河南省旅游管理系统是一种专为河南省旅游行业设计的信息管理系统&#xff0c;旨在整合和管理河南省的旅游资源信息&#xff0c;为游客提供准确、全面的旅游攻略和服务。以下是对该系统的详细介绍&#xff1a; 一、系统背景与意义 河南省作为中国的中部省份&…...

arm 下 多线程访问同一变量 ,使用原子操作 性能差问题

arm下原子操作性能差的原因 Linux Kernel(armv8-aarch64) 的原子操作的底层实现 - 极术社区 - 连接开发者与智能计算生态 arm 下如何解决 ARMs LSE (for atomics) and MySQL – MySQL On ARM – All you need to know about MySQL (and its variants) on ARM. arm 下lse 和…...

嵌入式工程师必学(143):模拟信号链基础

概述: 我们每天使用的许多电子设备,以及我们赖以生存的电子设备,如果不使用电子工程师设计的实际输入信号,就无法运行。 模拟信号链由四个主要元件组成:传感器、放大器、滤波器和模数转换器 (ADC)。这些传感器用于检测、调节模拟信号并将其转换为适合由微控制器或其他数…...

PyQt6/PySide6 的 QDialog 类

QDialog 是 PyQt6 或 PySide6 库中用于创建对话框的类。对话框是一种特殊的窗口&#xff0c;通常用于与用户进行短期交互&#xff0c;如输入信息、显示消息或选择选项等。QDialog 提供了丰富的功能和灵活性&#xff0c;使得开发者可以轻松地创建各种类型的对话框。下面我将详细…...

【AI日记】25.02.05 自由不是一种工具

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】 AI kaggle 比赛&#xff1a;Backpack Prediction Challenge感想&#xff1a;这次比赛的数据集的一大特点是信号过弱或者噪声过大&#xff0c;也是一大难点&#xff0c;即使kaggle 官方增加了一…...

【原子工具】快速幂 快速乘

题幂算.一切即1 阴阳迭变积微著&#xff0c;叠浪层峦瞬息功 莫道浮生千万事&#xff0c;元知万象一归宗 文章目录 快速幂原始快速幂&#xff08;O(logn)&#xff09;二分递归形式非递归形式 模下意义的快速幂&#xff08;O(logn)&#xff09;二分递归形式非递归形式 快速乘龟速…...

2024年12月 Scratch 图形化(四级)真题解析 中国电子学会全国青少年软件编程等级考试

202412 Scratch 图形化&#xff08;四级&#xff09;真题解析 中国电子学会全国青少年软件编程等级考试 一、选择题(共10题&#xff0c;共30分) 第 1 题 列表存放全班同学的身高&#xff0c;小猫运行下列程序&#xff0c;下列选项说法正确的是&#xff1f;&#xff08; &#…...

【面试宝典】机器学习:深度解析高频面试题与解答策略

目录 &#x1f354; 机器学习中特征的理解 &#x1f354; 机器学习三要素如何理解? &#x1f354; 机器学习中&#xff0c;有哪些特征选择的⼯程⽅法&#xff1f; &#x1f354; 机器学习中的正负样本 &#x1f354; 线性分类器与⾮线性分类器的区别及优劣 &#x1f354…...

使用 ElementUI 和 Spring 实现稳定可靠的文件上传和下载功能

前端(ElementUI) 1. 文件上传 使用 el-upload 组件配置上传接口处理上传成功和失败<template><div><el-uploadclass="upload-demo"action="http://your-server-url/upload":on-success="handleSuccess":on-error="handle…...

Linux驱动---字符设备

目录 一、基础简介 1.1、Linux设备驱动分类 1.2、字符设备驱动概念 二、驱动基本构成 2.1、驱动模块的加载和卸载 2.2、添加LICENNSE以及其他信息 三、字符设备驱动开发步骤 3.1、分配主次设备号 3.1.1 主次设备号 3.1.2静态注册设备号 3.1.3动态注册设备号 3.1.4释…...

FastReport.NET控件篇之交叉表控件

认识交叉表 上面是交叉表的原型&#xff0c;关键的三个单元格。 单元格①&#xff1a;用于扩展行数据&#xff0c;譬如打印学生成绩表时&#xff0c;每个学生一行&#xff0c;那么这个地方就是以学生姓名列进行打印。 单元格②&#xff1a;用于扩展列数据&#xff0c;譬如打印…...

构建高效复杂系统的关键:架构与模块详解

目录 一、复杂系统组成 二、接入系统 (Access System) 三、应用系统 (Application System) 四、基础平台 (Foundation Platform) 五、中间件 (Abundant External Middleware) 六、支撑系统 (Supporting System) 七、总结 参考文章 干货分享&#xff0c;感谢您的阅读&am…...