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

DS图(中)(19)

文章目录

  • 前言
  • 一、图的遍历
    • 广度优先遍历
    • 深度优先遍历
  • 二、最小生成树
    • Kruskal算法
    • Prim算法
    • 两种方法对比
  • 总结


前言

  承上启下,我们来学习下图的中篇!!!


一、图的遍历

  图的遍历指的是遍历图中的顶点,主要有 广度优先遍历 和 深度优先遍历 两种方式。

广度优先遍历

  广度优先遍历又称BFS,其遍历过程类似于二叉树的层序遍历,从起始顶点开始一层一层向外进行遍历。

在这里插入图片描述
广度优先遍历的实现:

  • 广度优先遍历需要借助一个队列和一个标记数组,利用队列先进先出的特点实现一层一层向外遍历,利用标记数组来记录各个顶点是否被访问过。
  • 刚开始时将起始顶点入队列,并将起始顶点标记为访问过,然后不断从队列中取出顶点进行访问,并判断该顶点是否有邻接顶点,如果有邻接顶点并且该邻接顶点没有被访问过,则将该邻接顶点入队列,并在入队列后立即将该邻接顶点标记为访问过。
		void BFS(const V& src)				{size_t srci = GetVertexIndex(src);// 队列和标记数组queue<int> q;vector<bool> visited(_vertexs.size(), false);q.push(srci);visited[srci] = true;int levelSize = 1;size_t n = _vertexs.size();while (!q.empty()){// 一层一层出for (int i = 0; i < levelSize; ++i){int front = q.front();q.pop();cout << front << ":" << _vertexs[front] << " ";// 把front顶点的邻接顶点入队列for (size_t i = 0; i < n; ++i){if (_matrix[front][i] != MAX_W){if (visited[i] == false){q.push(i);visited[i] = true;}}}}cout << endl;levelSize = q.size();}cout << endl;}
  • 为了防止顶点被重复加入队列导致死循环,因此需要一个标记数组,当一个顶点被访问过后就不应该再将其加入队列了。

  • 如果当一个顶点从队列中取出访问时才再将其标记为访问过,也可能会存在顶点被重复加入队列的情况,比如当图中的顶点B出队列时,顶点C作为顶点B的邻接顶点并且还没有被访问过(顶点C还在队列中),此时顶点C就会再次被加入队列,因此最好在一个顶点被入队列时就将其标记为访问过。

  • 如果所给图不是一个连通图,那么从一个顶点开始进行广度优先遍历,无法遍历完图中的所有顶点,这时可以遍历标记数组,查看哪些顶点还没有被访问过,对于没有被访问过的顶点,则从该顶点处继续进行广度优先遍历,直到图中所有的顶点都被访问过。

深度优先遍历

  深度优先遍历又称DFS,其遍历过程类似于二叉树的先序遍历,从起始顶点开始不断对顶点进行深入遍历。

在这里插入图片描述
深度优先遍历的实现:

  1. 深度优先遍历可以通过递归实现,同时也需要借助一个标记数组来记录各个顶点是否被访问过。
  2. 从起始顶点处开始进行递归遍历,在遍历过程中先对当前顶点进行访问,并将其标记为访问过,然后判断该顶点是否有邻接顶点,如果有邻接顶点并且该邻接顶点没有被访问过,则递归遍历该邻接顶点。
		void _DFS(size_t srci, vector<bool>& visited){cout << srci << ":" << _vertexs[srci] << endl;visited[srci] = true;// 找一个srci相邻的没有访问过的点,去往深度遍历for (size_t i = 0; i < _vertexs.size(); ++i){if (_matrix[srci][i] != MAX_W && visited[i] == false){_DFS(i, visited);}}}void DFS(const V& src){size_t srci = GetVertexIndex(src);vector<bool> visited(_vertexs.size(), false);_DFS(srci, visited);}
  • 如果所给图不是一个连通图,那么从一个顶点开始进行深度优先遍历,无法遍历完图中的所有顶点,这时可以遍历标记数组,查看哪些顶点还没有被访问过,对于没有被访问过的顶点,则从该顶点处继续进行深度优先遍历,直到图中所有的顶点都被访问过。

二、最小生成树

关于最小生成树

  • 一个连通图的最小连通子图称为该图的生成树,若连通图由 n 个顶点组成,则其生成树必含 n 个顶点和 n−1 条边,最小生成树指的是一个图的生成树中,总权值最小的生成树。

  • 连通图中的每一棵生成树都是原图的一个极大无环子图,从其中删去任何一条边,生成树就不再连通,在其中引入任何一条新边,都会形成一条回路。

  1. 对于各个顶点来说,除了第一个顶点之外,其他每个顶点想要连接到图中,至少需要一条边使其连接进来,所以由 n 个顶点的连通图的生成树有 n 个顶点和 n−1 条边。

  2. 对于生成树来说,图中的每个顶点已经连通了,如果再引入一条新边,那么必然会使得被新边相连的两个顶点之间存在一条直接路径和一条间接路径,即形成回路。

  3. 最小生成树是图的生成树中总权值最小的生成树,生成树是图的最小连通子图,而连通图是无向图的概念,有向图对应的是强连通图,所以最小生成树算法的处理对象都是无向图。

综上,我们可以得出以下生成 最小生成树 的准则

  1. 只能使用图中的边来构造最小生成树。
  2. 只能使用恰好 n−1 条边来连接图中的 n 个顶点。
  3. 选用的 n−1 条边不能构成回路。

构造最小生成树的算法有 Kruskal算法 和 Prim算法 ,这两个算法都采用了逐步求解的贪心策略。

Kruskal算法

Kruskal算法的基本思想如下:

  1. 构造一个含 n 个顶点、不含任何边的图作为最小生成树,对原图中的各个边按权值进行排序。
  2. 每次从原图中选出一条最小权值的边,将其加入到最小生成树中,如果加入这条边会使得最小生成树中构成回路,则重新选择一条边。
  3. 按照上述规则不断选边,当选出 n−1 条合法的边时,则说明最小生成树构造完毕,如果无法选出 n−1 条合法的边,则说明原图不存在最小生成树。

在这里插入图片描述

还记得我们之前学过的并查集么,如果忘记的话,快去复习一下吧!

  • 根据原图设置最小生成树的顶点集合,以及顶点与下标的映射关系,开辟最小生成树的邻接矩阵空间,并将矩阵中的值初始化为 MAX_W ,表示刚开始时最小生成树中不含任何边。

  • 遍历原图的邻接矩阵,按权值将原图中的所有边添加到优先级队列(小堆)中,为了避免重复添加相同的边,在遍历原图的邻接矩阵时只应该遍历矩阵的一半。

  • 使用一个并查集来辅助判环操作,刚开始时图中的顶点各自为一个集合,当两个顶点相连时将这两个顶点对应的集合进行合并,使得连通的顶点在同一个集合,这样通过并查集就能判断所选的边是否会使得最小生成树中构成回路,如果所选边连接的两个顶点本就在同一个集合,那么加入这条边就会构成回路。

  • 使用 count 和 totalWeight 分别记录所选边的数量和最小生成树的总权值,当 count 的值等于 n−1 时则停止选边,此时可以将最小生成树的总权值作为返回值进行返回。

  • 每次选边时从优先级队列中获取一个权值最小的边,并通过并查集判断这条边连接的两个顶点是否在同一个集合,如果在则重新选边,如果不在则将这条边添加到最小生成树中,并将这条边连接的两个顶点对应的集合进行合并,同时更新 count 和 totalWeight 的值。

  • 当选边结束时,如果 count 的值等于 n−1 ,则说明最小生成树构造成功,否则说明原图无法构造出最小生成树。

		typedef Graph<V, W, MAX_W, Direction> Self;struct Edge{size_t _srci;size_t _dsti;W _w;Edge(size_t srci, size_t dsti, const W& w):_srci(srci),_dsti(dsti),_w(w){}bool operator>(const Edge& e) const{return _w > e._w;}};W Kruskal(Self& minTree){size_t n = _vertexs.size();minTree._vertexs = _vertexs;minTree._indexMap = _indexMap;minTree._matrix.resize(n);for (size_t i = 0; i < n; ++i){minTree._matrix[i].resize(n, MAX_W);}priority_queue<Edge, vector<Edge>, greater<Edge>> minque;for (size_t i = 0; i < n; ++i){for (size_t j = 0; j < n; ++j){if (i < j && _matrix[i][j] != MAX_W){minque.push(Edge(i, j, _matrix[i][j]));}}}// 选出 n - 1 条边int size = 0;W totalW = W();UnionFindSet ufs(n);while (!minque.empty()){Edge min = minque.top();minque.pop();if (!ufs.InSet(min._srci, min._dsti)){//cout << _vertexs[min._srci] << "->" << _vertexs[min._dsti] <<":"<<min._w << endl;minTree._AddEdge(min._srci, min._dsti, min._w);ufs.Union(min._srci, min._dsti);++size;totalW += min._w;}else{//cout << "构成环:";//cout << _vertexs[min._srci] << "->" << _vertexs[min._dsti] << ":" << min._w << endl;}}if (size == n - 1){return totalW;}else{return W();}}
  • 在获取图的最小生成树时,会以无参的方式定义一个最小生成树对象,然后用原图对象调用上述 Kruskal函数 ,通过输出型参数的方式获取原图的最小生成树,由于我们定义了一个带参的构造函数,使得编译器不再生成默认构造函数,因此需要通过 default 关键字强制生成 Graph类 的默认构造函数。

  • 一条边包含两个顶点和边的权值,可以定义一个Edge结构体来描述一条边,结构体内包含边的源顶点和目标顶点的下标以及边的权值,在使用优先级队列构造小堆结构时,需要存储的对象之间能够支持 > 运算符操作,因此需要对Edge结构体的 > 运算符进行重载,将其重载为边的权值的比较。

  • 当选出的边不会构成回路时,需要将这条边插入到最小生成树对应的图中,此时已经知道了这条边的源顶点和目标顶点对应的下标,可以在 Graph类 中新增一个 _AddEdge 子函数,该函数支持通过源顶点和目标顶点的下标向图中插入边,而 Graph类 中原有的 AddEdge函数 可以复用这个 _AddEdge 子函数。

  • 最小生成树不一定是唯一的,特别是当原图中存在很多权值相等的边的时候。

  • 上述代码中通过优先级队列构造小堆来依次获取权值最小的边,你也可以通过其他排序算法按权值对边进行排序,然后按权值从小到大依次遍历各个边进行选边操作。

Prim算法

Prim算法的基本思想如下:

  1. 构造一个含 n 个顶点、不含任何边的图作为最小生成树,将图中的顶点分为两个集合,forest 集合中的顶点是已经连接到最小生成树中的顶点,remain 集合中的顶点是还没有连接到最小生成树中的顶点,刚开始时 forest 集合中只包含给定的起始顶点。

  2. 每次从连接 forest 集合与 remain 集合的所有边中选出一条权值最小的边,将其加入到最小生成树中,由于选出来的边对应的两个顶点一个属于 forest 集合,另一个属于 remain 集合,因此这种方法是天然不会构成回路的。

  3. 按照上述规则不断选边,当选出 n−1 条边时,所有的顶点都已经加入到了 forest 集合,此时最小生成树构造完毕,如果无法选出 n−1 条边,则说明原图不存在最小生成树。

在这里插入图片描述

  • 根据原图设置最小生成树的顶点集合,以及顶点与下标的映射关系,开辟最小生成树的邻接矩阵空间,并将矩阵中的值初始化为 MAX_W ,表示刚开始时最小生成树中不含任何边。

  • 使用一个 forest 数组来表示各个顶点是否在 forest 集合中,刚开始时只有起始顶点在 forest 集合中,并将所有从起始顶点连接出去的边加入优先级队列(小堆),这些边就是刚开始时连接 forest 集合与 remain 集合的边。

  • 使用 count 和 totalWeight 分别记录所选边的数量和最小生成树的总权值,当 count 的值等于 n−1 时则停止选边,此时将最小生成树的总权值作为返回值进行返回。

  • 每次选边时从优先级队列中获取一个权值最小的边,将这条边添加到最小生成树中,并将这条边的目标顶点加入 forest 集合中,同时更新 count 和 totalWeight 的值。

  • 此外,还需要将从这条边的目标顶点连接出去的边加入优先级队列,但是需要保证加入的边的目标顶点不能在 forest 集合,否则后续选出源顶点和目标顶点都在 forest 集合的边就会构成回路。

  • 需要注意的是,每次从优先级队列中选出一个权值最小的边时,还需要保证选出的这条边的目标顶点不在 forest 集合中,避免构成回路。虽然向优先级队列中加入边时保证了加入的边的目标顶点不在 forest 集合中,但经过后续不断的选边,可能会导致之前加入优先级队列中的某些边的目标顶点也被加入到了 forest 集合中。

  • 当选边结束时,如果 count 的值等于 n−1 ,则说明最小生成树构造成功,否则说明原图无法构造出最小生成树。

		W Prim(Self& minTree, const V& src){size_t srci = GetVertexIndex(src);size_t n = _vertexs.size();minTree._vertexs = _vertexs;minTree._indexMap = _indexMap;minTree._matrix.resize(n);for (size_t i = 0; i < n; ++i){minTree._matrix[i].resize(n, MAX_W);}/*set<int> X;set<int> Y;X.insert(srci);for (size_t i = 0; i < n; ++i){if (i != srci){Y.insert(i);}}*/vector<bool> X(n, false);vector<bool> Y(n, true);X[srci] = true;Y[srci] = false;// 从X->Y集合中连接的边里面选出最小的边priority_queue<Edge, vector<Edge>, greater<Edge>> minq;// 先把srci连接的边添加到队列中for (size_t i = 0; i < n; ++i){if (_matrix[srci][i] != MAX_W){minq.push(Edge(srci, i, _matrix[srci][i]));}}cout << "Prim开始选边" << endl;size_t size = 0;W totalW = W();while (!minq.empty()){Edge min = minq.top();minq.pop();// 最小边的目标点也在X集合,则构成环if (X[min._dsti]){//cout << "构成环:";//cout << _vertexs[min._srci] << "->" << _vertexs[min._dsti] << ":" << min._w << endl;}else{minTree._AddEdge(min._srci, min._dsti, min._w);//cout << _vertexs[min._srci] << "->" << _vertexs[min._dsti] << ":" << min._w << endl;X[min._dsti]= true;Y[min._dsti] = false;++size;totalW += min._w;if (size == n - 1)break;for (size_t i = 0; i < n; ++i){if (_matrix[min._dsti][i] != MAX_W && Y[i]){minq.push(Edge(min._dsti, i, _matrix[min._dsti][i]));}}}	}if (size == n - 1){return totalW;}else{return W();}}

两种方法对比

  • Prim算法构造最小生成树的思想在选边时是不需要判环,但上述利用优先级队列实现的过程中仍需判环,如果在每次选边的时候能够通过某种方式,从连接 forest 集合和 remain 集合的所有边中选出权值最小的边,那么就无需判环,但这两个集合中的顶点是不断在变化的,每次选边时都遍历连接两个集合的所有边,该过程的时间复杂度较高(达到O(N^3)的级别),所以我们采用 vector< bool > 的方法来表示两个集合,进而解决了判环的问题
  • Kruskal算法本质是一种全局的贪心,每次选边时都是在所有边中选出权值最小的边,而Prim算法本质是一种局部的贪心,每次选边时是从连接 forest 集合和 remain 集合的所有边中选出权值最小的边。

总结

  困了,接下来还有最短路径问题,就等早上起来再写吧!

相关文章:

DS图(中)(19)

文章目录 前言一、图的遍历广度优先遍历深度优先遍历 二、最小生成树Kruskal算法Prim算法两种方法对比 总结 前言 承上启下&#xff0c;我们来学习下图的中篇&#xff01;&#xff01;&#xff01; 一、图的遍历 图的遍历指的是遍历图中的顶点&#xff0c;主要有 广度优先遍历 …...

Vue Dom截图插件,截图转Base64 html2canvas

安装插件 npm install html2canvas --save插件使用 <template><div style"padding: 10px;"><div ref"imageTofile" class"box">发生什么事了</div><button click"toImage" style"margin: 10px;&quo…...

Unity3D仿星露谷物语开发小结1

1、Cinemachine的作用及使用方法 &#xff08;1&#xff09;作用 控制Camera的模块&#xff0c;实现摄像机的复杂控制&#xff0c;比如角色的跟随&#xff0c;限制Camera的区域 &#xff08;2&#xff09;使用方法 在已有Main Camera的情况下&#xff0c; 通过【GameObject -&…...

graylog初体验

最近graylog比较火&#xff0c;部署了一个来测试下&#xff0c;看下后续能不能代替目前占用资源比较多的elk&#xff0c;目前未对graylog性能进行深入测试&#xff0c;只是简单体验了下&#xff0c;graylog的UI比较简陋&#xff0c;但是在报警以及权限方面优于ELK&#xff0c;整…...

15.PPT:文静-云计算行业发展【29】

目录 NO123​ NO345​ NO6​ NO78 NO9/10/11/12​ NO123 设计→幻灯片大小→自定义幻灯片大小→ 全屏显示&#xff08;16&#xff1a;9&#xff09;→最大化 NO345 SmartArt 主题颜色2/6/9&#xff1a;形状样式&#xff1a;样式 加大行距加宽间距 NO6 NO78 设计→设置背景…...

高端入门:Ollama 本地高效部署DeepSeek模型深度搜索解决方案

目录 一、Ollama 介绍 二、Ollama下载 2.1 官网下载 2.2 GitHub下载 三、模型库 四、Ollmal 使用 4.1 模型运行&#xff08;下载&#xff09; 4.2 模型提问 五、Ollama 常用命令 相关推荐 一、Ollama 介绍 Ollama是一个专为在本地机器上便捷部署和运行大型语言模型&…...

MFC 的 CListCtrl 控件,使用SetItemState 方法来设置选中某个 item,如何达到效果和鼠标点击一致

1&#xff09;查询到的方法如下&#xff1a; // 假设你要选中第 2 行&#xff08;索引从 0 开始&#xff09; int nItem 1; // 取消所有其他选中项 m_ListCtrl.SetItemState(-1, 0, LVIS_SELECTED); // 设置选中状态&#xff0c;并确保它具有焦点 m_ListCtrl.SetItemStat…...

一文读懂:TCP网络拥塞的应对策略与方案

TCP&#xff08;传输控制协议&#xff09;是互联网中广泛使用的可靠传输协议&#xff0c;它通过序列号、确认应答、重发控制、连接管理以及窗口控制等机制确保数据的可靠传输。然而&#xff0c;在网络环境中&#xff0c;由于多个主机共享网络资源&#xff0c;网络拥塞成为了一个…...

深度整理总结MySQL——子查询的工作原理

子查询的工作原理 前言为什么开发人员喜欢写子查询查询重写条件化简移除不必要的括号常量传递&#xff08;constant_propagation&#xff09;移除没用的条件&#xff08;trivial_condition_removal&#xff09;HAVING子句和WHERE子句的合并 常量表检测外连接消除 子查询子查询语…...

20240824 美团 笔试

文章目录 1、单选题1.11.21.31.41.51.61.71.81.91.101.111.121.131.141.151.161.171.181.191.202、编程题2.12.2岗位:硬件开发工程师(嵌入式系统软件开发方向) 题型:20 道单选题,2 道编程题题 1、单选题 1.1 C 语言中,如果输入整数 v 是 2 的幂,下面表达式中哪个会返…...

Windows图形界面(GUI)-QT-C/C++ - QT 文本编辑控件详解

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 概述 1. QLineEdit 1.1 特点 1.2 属性 1.3 常用方法 1.4 拓展应用 2. QTextEdit 2.1 特点 2.2 属性 2.3 常用方法 2.4 拓展应用 3. QPlainTextEdit 3.1 特点 3.2 属性 3.3…...

IDEA中Resolving Maven dependencies卡着不动解决方案

一、修改settings.xml Maven配置阿里云仓库主要通过修改Maven的settings.xml文件来实现‌。以下是具体步骤: ‌1、找到settings.xml文件‌: 通常位于Maven安装目录下的conf文件夹中,或者在用户目录下的.m2文件夹中(如果用户自定义了settings.xml的位置)。 2、‌编辑se…...

go数据结构学习笔记

本博文较为完整的实现了go的链表、栈&#xff0c;队列&#xff0c;树&#xff0c;排序&#xff0c;链表包括顺序链表&#xff0c;双向链表&#xff0c;循环链表&#xff0c;队列是循环队列&#xff0c;排序包含冒牌、选择 1.链表 1.1 顺序链表 type LNode struct {data intn…...

【后端开发】系统设计101——Devops,Git与CICD,云服务与云原生,Linux,安全性,案例研究(30张图详解)

【后端开发】系统设计101——Devops&#xff0c;Git与CICD&#xff0c;云服务与云原生&#xff0c;Linux&#xff0c;安全性&#xff0c;案例研究&#xff08;30张图详解&#xff09; 文章目录 1、DevopsDevOps与SRE与平台工程的区别是什么&#xff1f;什么是k8s&#xff08;Ku…...

Google地图瓦片爬虫——进阶版

紧接上一篇——Google地图瓦片爬虫 clash节点自动切换 为了防止一个IP地址访问频率过快问题&#xff0c;自动切换clash的节点 def change_node(is_stop):while True:_r requests.get("http://127.0.0.1:11053/proxies", headersclash_headers, verifyFalse)# 这里…...

免费windows pdf编辑工具

Epdf&#xff08;完全免费&#xff09; 作者&#xff1a;不染心 时间&#xff1a;2025/2/6 Github: https://github.com/dog-tired/Epdf Epdf Epdf 是一款使用 Rust 编写的 PDF 编辑器&#xff0c;目前仍在开发中。它提供了一系列实用的命令行选项&#xff0c;方便用户对 PDF …...

解锁C#数据校验:从基础到实战的进阶之路

一、引言&#xff1a;数据校验为何如此重要&#xff1f; 在软件开发的广袤领域中&#xff0c;数据校验宛如一座坚固的堡垒&#xff0c;守护着系统的稳定与安全。它是确保数据质量的关键防线&#xff0c;能有效避免错误数据的流入&#xff0c;进而提升系统的整体性能和可靠性。…...

Redis的通用命令

⭐️前言⭐️ 本文主要介绍Redis的通用命令 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f349;博主将持续更新学习记录收获&#xff0c;友友们有任何问题可以在评论区留言 &#x1f349;博客中涉及源码及博主日常练习代码均已上传GitHub &#x1f4cd;内容导…...

设计模式六大原则和单例模式

设计模式 目的 实现可重用解决方案&#xff0c;构筑易维护、可扩展的软件系统。 六大原则 单一职责&#xff1a; 类的职责单一&#xff0c;一个方法做一件事。 开闭原则&#xff1a; 拓展开放&#xff0c;修改关闭。 里氏替换&#xff1a; 父类能出现的地方&#xff0c;子…...

Redis性能优化

1.是否使用复杂度过高的命令 首先&#xff0c;第一步&#xff0c;你需要去查看一下 Redis 的慢日志&#xff08;slowlog&#xff09;。 Redis 提供了慢日志命令的统计功能&#xff0c;它记录了有哪些命令在执行时耗时比较久。 查看 Redis 慢日志之前&#xff0c;你需要设置慢…...

AI图片售卖:是暴利新风口还是虚幻泡沫?哪些平台适合售卖AI图片

还记得去年大火的Midjourney吗&#xff1f;今年4月&#xff0c;Midjourney又发布了备受期待的V7版本&#xff0c;带来了更高的图像质量和创新功能。使用Midjourney、Stable Diffusion、DALLE等AI图片生成工具&#xff0c;创作者只需输入关键词即可获得高质量的原创图片。这一变…...

软件功能模块归属论证方法

文章目录 **一、核心设计原则****二、论证方法****三、常见决策模式****四、验证方法****五、反模式警示****总结** 在讨论软件功能点应该归属哪些模块时&#xff0c;并没有放之四海而皆准的固定方法&#xff0c;但可以通过系统化的论证和设计原则来做出合理决策。以下是常见的…...

30.【新型数据架构】-区块链数据架构

30.【新型数据架构】-区块链数据架构:分布式账本,不可篡改性,用于数据溯源 一、区块链数据架构的本质:分布式账本的革新 区块链的核心是分布式账本技术(Distributed Ledger Technology, DLT),它颠覆了传统中心化数据库的架构模式: 去中心化存储: 账本数据不再集中存储…...

figma 和蓝湖 有什么区别

以下是 Figma 和蓝湖的详细对比分析&#xff1a; 核心定位区别 维度Figma蓝湖本质全功能云端设计工具设计协作与交付平台核心功能设计原型协作开发交付设计稿交付标注切图协作设计能力✅ 完整矢量设计工具❌ 无设计功能&#xff08;需导入其他工具文件&#xff09;适用阶段全流…...

《视觉SLAM十四讲》自用笔记 第二讲:SLAM系统概述

在rm队伍里作为算法组梯队队员度过了一个赛季&#xff0c;为了促进和负责其他工作的算法组成员的交流&#xff0c;我决定在接下来的半个学期里&#xff08;可能更快&#xff09;读完这本书&#xff0c;并将其中的部分理论应用于我自制的雷达导航小车上。 以下为第二讲的部分笔记…...

Docker容器化技术概述与实践

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker 容器化的基本概念 Docker 容器化是一种轻量级的虚拟化技术&#xff0c;通过将应用程序及其依赖项打包到一个可移植的容器中&#xff0c;使其在任何兼容 Docker 的环境中都能运行。与传统的虚拟机技术不同…...

centos中的ulimit命令

centos中的ulimit命令 ulimit的作用CENTOS系统文件配置配置文件地址配置格式 配置方法 ulimit的作用 ulimit用于限制shell启动进程所占用的资源&#xff0c;支持以下各种类型的限制&#xff1a;所创建的内核文件的大小、进程数据块的大小、Shell进程创建文件的大小、内存锁住的…...

【案例分享】如何借助JS UI组件库DHTMLX Suite构建高效物联网IIoT平台

随着工业领域数字化进程的持续加快&#xff0c;Web 技术在实现实时监控、数据可视化与控制系统等方面正扮演着越来越核心的角色。来自智利的科技企业 Wise Data Global 就是这一趋势中的积极践行者。他们借助慧都科技代理的 DHTMLX Suite JavaScript UI 控件库&#xff0c;为遥…...

Spring AI之RAG入门

目录 1. 什么是RAG 2. RAG典型应用场景 3. RAG核心流程 3.1. 检索阶段 3.2. 生成阶段 4. 使用Spring AI实现RAG 4.1. 创建项目 4.2. 配置application.yml 4.3. 安装ElasticSearch和Kibana 4.3.1. 安装并启动ElasticSearch 4.3.2. 验证ElasticSearch是否启动成功 …...

2025年牛客网秋招/社招高质量 Java 面试八股文整理

Java 面试 不论是校招还是社招都避免不了各种面试。笔试&#xff0c;如何去准备这些东西就显得格外重要。不论是笔试还是面试都是有章可循的。关键在于理解企业的需求&#xff0c;明确自己的定位&#xff0c;以及掌握一定的应试技巧。 笔试部分&#xff0c;通常是对基础知识、…...