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

数据结构 图 并查集 遍历方法 最短路径算法 最小生成树算法 简易代码实现

文章目录

  • 前言
  • 并查集
  • 遍历方法
    • 广度优先遍历
    • 深度优先遍历
  • 最小生成树算法
    • Kruskal算法
    • Prim算法
  • 最短路径算法
    • Dijkstra算法
    • BellmanFord算法
    • FloydWarshall算法
  • 全部代码链接

前言

  1. 图是真的难,即使这些我都学过一遍,再看还是要顺一下过程;
  2. 说明方式按照 概念-> 实现思想 -> 代码逻辑 —> 代码 的方式进行 ;
  3. 图片多来自于《算法导论》 等书 ;
  4. 后续可能会做更详细的补充

并查集

概念:
并查集(Disjoint Set)是一种用于处理集合合并与查询问题的数据结构。它主要支持两种操作:合并(Union)和查找(Find)。

在并查集中,每个元素都被看作一个节点,多个节点组成一个集合。每个集合通过一个代表元素来表示,通常选择集合中的某个元素作为代表元素。

合并操作将两个不相交的集合合并成一个集合,即将其中一个集合的代表元素指向另一个集合的代表元素。

查找操作用于确定某个元素所属的集合,即找到该元素所在集合的代表元素。

通过这两种操作,可以高效地判断两个元素是否属于同一个集合,以及将不相交的集合合并成一个集合。

实现逻辑

  1. 下标代表节点
  2. 下标内的值为负代表为根节点
  3. 根节点的绝对值为该树的总节点个数
  4. 下标内的值为正值,代表的是其父亲节点的下标

在这里插入图片描述在这里插入图片描述
实现代码

// 并查集代码 
#include <vector>class DisiointSetUnion
{
private:std::vector<int> _set; public://数组下标本身就是存储的内容//DSU为用一维数组抽象的森林(可含多棵树)//默认 -1 表示默认全为单独的根节点DisiointSetUnion(int size):_set(size, -1){}//找到根节点下标size_t FindRoot(int x){// 根节点存储负值,且负值的绝对值为该树节点的数量;// 如果不为根节点,返回其父亲节点的下标;while (_set[x] >= 0){x = _set[x];}// 如果要压缩路径可在该函数内部添加后续方法return x; }void Union(int x1, int x2){int root1 = FindRoot(x1);int root2 = FindRoot(x2);if (root1 != root2){_set[root1] += _set[root2];_set[ root2 ] = root1;}}//判断两节点是否一颗树中bool InSet(int x1, int x2){int root1 = FindRoot(x1);int root2 = FindRoot(x2);if (root1 == root2){return true;}else{return false;}}//计算有几个树// 通过计算负值数size_t SetCount(){size_t count = 0 ;for (size_t i = 0; i < _set.size(); i++){if (_set[i] < 0){count++;}}return count; }};

基本概念
节点(Vertex):也称为顶点,表示图中的元素。节点可以有附加的属性,如权重、颜色等。

边(Edge):表示节点之间的连接关系。边可以是有向的(有方向性)或无向的(无方向性)。有向边由起始节点指向目标节点,无向边没有方向。

路径(Path):是由边连接的节点序列。路径的长度是指路径上边的数量。

环(Cycle):是一条起始节点和终止节点相同的路径。

连通图(Connected Graph):如果图中任意两个节点之间都存在路径,则称该图为连通图。

子图(Subgraph):由图中一部分节点和边组成的图。

权重(Weight):边可以有权重,表示节点之间的关联程度或距离。

入度(In-degree)和出度(Out-degree):对于有向图,入度表示指向该节点的边的数量,出度表示从该节点出发的边的数量。

邻接点(Adjacent Vertex):与给定节点直接相连的节点

实现逻辑:
在这里插入图片描述
代码实现:

//邻接矩阵实现图//Direction为是否为有向图的标志位//INT_MAX为不存在的边的标识值// V 为顶点名类型 template<class V, class W, W MAX_W = INT_MAX, bool Direction = false>class Graph{private: //成员变量map<V, size_t> _vIndexMap; // 存储顶点名与顶点在数组中的下标   顶点名->数组中下标vector<V> _vertexs;		   // 存储顶点						   下标—>数组名vector<vector<W>> _matrix; // 图   //临界矩阵  // 此中建立边的关系public: //类内类//类内定义类,Edge类是Graph类的友元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& eg){return _w < eg._w;}bool operator>(const Edge& eg){return _w > eg._w;}};public: // 成员方法 typedef Graph<V, W, MAX_W, Direction> Self;Graph() = default;//只初始化节点,没有边Graph(const V* vertexs, size_t n){_vertexs.reserve(n);// 对_vIndexMap 、 _vertexs 初始化for (size_t i = 0; i < n; ++i){_vertexs.push_back(vertexs[i]);_vIndexMap[vertexs[i]] = i;}// 对 _matrix 初始化_matrix.resize(n);for (auto& e : _matrix){e.resize(n, MAX_W);}}// 根据顶点名查找下标size_t GetVertexIndex(const V& v){auto ret = _vIndexMap.find(v);if (ret != _vIndexMap.end()){return ret->second;}else{printf(" 查找顶点不存在\n");return -1;}}// 添加边,被AddEdge函数调用void _AddEdge(size_t srci, size_t dsti, const W& w){//发生了越界错误  //代码的逻辑有问题 ? ? ? ? ? _matrix[srci][dsti] = w;if (Direction == false){_matrix[dsti][srci] = w;}}// 调用_AddEdge函数添加边void AddEdge(const V& src, const V& dst, const W& w){size_t srci = GetVertexIndex(src);size_t dsti = GetVertexIndex(dst);_AddEdge(srci, dsti, w);}}

遍历方法

广度优先遍历

实现逻辑:
在这里插入图片描述
代码逻辑:在这里插入图片描述

代码实现:

		//测试运行成功!//如果为不完全连通的图怎么办???//src 为遍历的起始顶点//广度优先遍历//利用 队列 + 标记数组void BFS(const V& src){size_t srcindex = GetVertexIndex(src);vector<bool> visted;visted.resize(_vertexs.size(), false);// true代表已经被遍历过//队列的作用类似与二叉树层序遍历中队列的作用queue<int> q;q.push(srcindex);visted[srcindex] = true;size_t d = 1;  //代表广度遍历的层数 size_t dSize = 1;  //队列中剩余的顶点数while (!q.empty()){//只有当V为基础类型时,此行代码才通用 cout << src << "的" << d << "度的好友 ";while (dSize--){size_t front = q.front();q.pop();for (size_t i = 0; i < _matrix.size(); i++){if (visted[i] == false && _matrix[front][i] != MAX_W){只有当V为基础类型时,此行代码才通用cout << "[" << i << ":" << _vertexs[i] << "]";visted[i] = true;q.push(i);}}}cout << endl;dSize = q.size();d++;}cout << endl;}

深度优先遍历

实现逻辑:
在这里插入图片描述
代码实现:

//测试成功!// 递归实现 //思想也是类似与二叉树的递归遍历//深度优先遍历void DFS(const V& src){size_t srcindex = GetVertexIndex(src);vector<bool> visted;visted.resize(_vertexs.size(), false);_DFS(srcindex, visted);}//可以遍历不连通的树吗? //visited用于标志是否已经遍历过//深度优先遍历辅助函数void _DFS(size_t srcIndex, vector<bool>& visited){cout << "[" << srcIndex << _vertexs[srcIndex] << "]";visited[srcIndex] = true;for (size_t i = 0; i < _vertexs.size(); i++){if (visited[i] == false && _matrix[srcIndex][i] != MAX_W){_DFS(i, visited);}}}

最小生成树算法

概念:
最小生成树(Minimum Spanning Tree,简称MST)是一种在连通无向图中生成一棵树的算法,使得这棵树包含了图中的所有节点,并且边的权重之和最小。

最小生成树的特点是,它是一个无环的连通子图,其中包含了图中的所有节点,并且边的权重之和最小。

Kruskal算法

概念:
Kruskal算法:Kruskal算法是一种贪心算法,它按照边的权重从小到大的顺序逐步选择边,如果选择某条边不会形成环,则将该边加入到最小生成树中,直到最小生成树中包含了所有的节点。

实现逻辑:
在这里插入图片描述
代码实现:

// Kruskal算法寻找最小生成树// 最小生成树是在已存在的连通图上找到把所有点连起来且总权重最小的N-1条边(N为节点总数)// 每次先找最小边再经判断是否构成回路确定是否连接顶点// 判断是否构成回路用并查集?// 贪心算法,寻找局部最优解  W Kruskal(Self& minTree){size_t n = _vertexs.size();minTree._vertexs = _vertexs;minTree._vIndexMap = _vIndexMap;minTree._matrix.resize(n); // 注意深浅拷贝for (size_t i = 0; i < n; i++){//! ! ! ! !minTree._matrix[i].resize(n, MAX_W);}//创建一个堆,用来快速找出最小路径priority_queue<Edge, vector<Edge>, Mygreater>  minque;for (size_t i = 0; i < n; i++){for (size_t j = 0; j < n; j++){//i < j 这个条件的原因是: 生成最小生成树的依据原图为无向图//最小生成树本身也是无向的if (i < j && _matrix[i][j] != MAX_W){minque.push(Edge(i, j, _matrix[i][j]));}}}//开始选边 + 判是否成环int size = 0;  // 计算是否满足 N - 1条边的条件W total = W(); // 计算生成的最小生成树的总权重  并查集类对象DisiointSetUnion dsf(n);while (!minque.empty()){Edge min = minque.top();minque.pop();if (!dsf.InSet(min._dsti, min._srci)){cout << _vertexs[min._srci] << "->" << _vertexs[min._dsti] << ":" << min._w << endl;minTree._AddEdge(min._srci, min._dsti, min._w);dsf.Union(min._srci, min._dsti);size++;total += min._w;}else{// 构成了环cout << "成环:" << _vertexs[min._srci] << "->" << _vertexs[min._dsti] << ":" << min._w << endl;}}if (size == n - 1){return total;}else{return W();}}

Prim算法

概念:Prim算法:Prim算法也是一种贪心算法,它从一个起始节点开始,逐步选择与当前最小生成树相邻的边中权重最小的边,并将其加入到最小生成树中,直到最小生成树中包含了所有的节点。

实现逻辑:在这里插入图片描述
代码实现:

//Prim算法寻找最小生成树//src为生成最小生成树的起始点W Prim(Self& minTree, const V& src){size_t srci = GetVertexIndex(src); // 不是给顶点名找下标的函数么……  // ! ! ! ! ! !size_t n = _vertexs.size(); minTree._vertexs = _vertexs ;minTree._vIndexMap = _vIndexMap; minTree._matrix.resize(n);for (size_t i = 0; i < n; i++){minTree._matrix[i].resize(n, MAX_W);}// 记录是否已经被连接//为什么要有两个?vector<bool> X(n, false);vector<bool> Y(n, true);X[srci] = true; Y[srci] = false;priority_queue<Edge, vector<Edge>, Mygreater> minq;for (size_t i = 0; i < n; i++){if (_matrix[srci][i] != MAX_W){minq.push(Edge(srci, i, _matrix[srci][i]));}}//开始选边size_t size = 0;W total = W();while (!minq.empty()){Edge min = minq.top();minq.pop();if (X[min._dsti]){//成环}else{minTree._AddEdge(min._srci, min._dsti, min._w);X[min._dsti] = true;Y[min._srci] = false;size++;total += min._w;if (size == n - 1){//最多n-1条路break;}for (int i = 0; i < n; i++){if (_matrix[min._dsti][i] != MAX_W && Y[i]) // ? ? ? Y[i]? ? ? {minq.push(Edge(min._dsti, i, _matrix[min._dsti][i]));}}}}if (size == n - 1){return total;}else{return W();}}

最短路径算法

概念:最短路径算法用于找到两个节点之间的最短路径,即路径上边的权重之和最小的路径。

Dijkstra算法

概念:
Dijkstra算法:Dijkstra算法是一种贪心算法,用于解决单源最短路径问题,即从一个给定的起始节点到图中所有其他节点的最短路径。算法维护一个距离数组,记录从起始节点到每个节点的当前最短距离。算法每次选择距离起始节点最近的未访问节点,并更新其邻接节点的最短距离。重复这个过程直到所有节点都被访问

注意:不可处理存在负权值的图

实现逻辑:在这里插入图片描述
代码实现:

//时间复杂度为多少 ? ? ?// Dijkstra 不考虑负路径的问题,或者说无法处理父权值路径的图//Dijkstra 为最短路径算法//最短路径:即计算指定出发点到任意点的距离// dist 记录从出发点到该点的当前已更新的最短路径,注意是当前已更新的。  dist pPath 为输出参数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;// 已经确定的最短路径的集合// 满足什么条件确定最短路径不再更新 ?  // 被置为true后就不会再更新吗 ?  是 vector<bool> S(n, false);for (size_t j = 0; j < n; j++){// 1. 找出起始点直接连接的最短路径节点和其对应的权重// 用于记录/更新最短路径和该最短路劲对应的权重int u = 0;W min = MAX_W;// size_t v的for循环更新后会影响该循环结束时u的值for (size_t i = 0; i < n; i++){if (S[i] == false && dist[i] < min){u = i;min = dist[i];}}// 已选的最短路径不会再选了 S[u] = true;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; }}}}//不可用于打印FloydWarshall的结果//辅助打印最短路径结果void PrintShortPath(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++){size_t parent = pPath[i];cout << _vertexs[i] << "到起始顶点" << src <<"最小总权值为:" << dist[i] << "——最短路径为:";cout << _vertexs[i] << "<-";while (parent != srci){cout << _vertexs[parent] << "<-" ;parent = pPath[parent];}cout  << src  << endl;}}

BellmanFord算法

概念:
Bellman-Ford算法:Bellman-Ford算法是一种动态规划算法,用于解决单源最短路径问题,可以处理带有负权边的图。算法维护一个距离数组,记录从起始节点到每个节点的当前最短距离。算法通过对所有边进行松弛操作,即尝试通过更新路径来减小距离数组中的值。重复这个过程直到没有可以更新的路径或者存在负权环。

时间复杂度分析:
Dijkstra算法适用于没有负权边的图,时间复杂度为O(V^2)或O((V + E)logV),其中V是节点数,E是边数。Bellman-Ford算法适用于带有负权边的图,时间复杂度为O(VE),其中V是节点数,E是边数。

实现逻辑:
在这里插入图片描述
代码实现:

/ BellmanFord的时间复杂度为多少 ? 如何计算的 ?// BellmanFord可以处理负权值路径存在的场景 // 关于负权值环路的问题 : 不做考虑,这种情况就没有最小权值路径,权值延着负权值环路走会无限减小,直到负无穷大// BellmanFord和Dijkstra的区别在于无确认该点为最短路径的这一动作 ?;// 停止更新的条件: 1.是依据图的最大可更新次数停止更新 ||  2.本次更新没有新的最短路径出现bool BellmanFord(const V& src, vector<W>& dist, vector<int>& pPath){size_t n = _vertexs.size(); size_t srci = GetVertexIndex(src); dist.resize(n, MAX_W); pPath.resize(n, -1);// 更新出发顶点 srci 为缺省值(0)dist[srci] = W();// 最多更新n轮 , 因为极端情况为所有顶点排成一条线for (size_t k = 0; k < n; ++k){bool update = false;cout << "第" << k << "轮更新" << endl;for (size_t i = 0; i < n; ++i){for (size_t j = 0; j < n; ++j){// 实际上这个判断还隐含了条件 dist[i] != MAX_W ! ! ! ! ! ! !// 因为这个隐含条件达到了类似广度优先向外遍历更新最短路径的效果if (_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++){if (_matrix[i][j] != MAX_W && dist[i] + _matrix[i][j] < dist[j]){cout << "存在负权回路" << endl;return false; }}}return true; }

FloydWarshall算法

Floyd-Warshall算法的基本思想是通过中间节点逐步更新节点对之间的最短路径。算法维护一个二维数组D,其中D[i][j]表示节点i到节点j的最短路径长度。算法的核心是使用三重循环,对于每一对节点(i, j)和每一个可能的中间节点k,尝试更新D[i][j]的值,即通过节点k来缩短节点i到节点j的路径长度。

算法的具体步骤如下:

  1. 初始化二维数组D,将所有节点对之间的距离初始化为无穷大,但将节点自身到自身的距离初始化为0。

  2. 对于每一个中间节点k,遍历所有的节点对(i, j),尝试更新D[i][j]的值。更新的方式是比较D[i][j]的当前值和D[i][k] + D[k][j]的和,将较小的值赋给D[i][j]。

  3. 重复步骤2,对于每一个中间节点k,直到所有的节点对都被考虑过。

  4. 最终得到的二维数组D中,D[i][j]表示节点i到节点j的最短路径长度。

Floyd-Warshall算法的时间复杂度为O(V^3),其中V是节点数。由于需要遍历所有的节点对和中间节点,因此算法在处理大规模图时的效率可能较低。但它的优点是能够同时计算出所有节点对之间的最短路径,适用于需要获取全局最短路径信息的场景,例如网络路由算法中的链路状态路由协议。

实现逻辑:
在这里插入图片描述

// FloydWarshall算法求最短路径// vvpPath 中的值的含义为  ? ? ? 中间节点 ?   如果不存在中间节点就是指原本直接相连的点 ? 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();}}}for (size_t k = 0; k < n; k++){for (size_t i = 0; i < n; i++){for (size_t j = 0; j < n; j++){// k 为中间节点 !?if (vvDist[i][k] != MAX_W && vvDist[k][j] != MAX_W&& vvDist[i][k] + vvDist[k][j] < vvDist[k][j]){vvDist[i][j] = vvDist[i][k] + vvDist[k][j]; vvpPath[i][j] = vvpPath[k][j]; // ! ! ! ! !}}}//打印权值和路径for (size_t i = 0; i < n; i++){for (size_t j = 0; j < n; j++){if (vvDist[i][j] == MAX_W){printf("%3c", '*');}else{printf("%3d", vvDist[i][j]);}}cout << endl; }cout << endl; for (size_t i = 0; i < n; i++){for (size_t j = 0; j < n; j++){printf("%3d", vvpPath[i][j]);}cout << endl; }cout << "————————————————" << endl;}}

全部代码链接

代码链接——gitee

相关文章:

数据结构 图 并查集 遍历方法 最短路径算法 最小生成树算法 简易代码实现

文章目录 前言并查集图遍历方法广度优先遍历深度优先遍历 最小生成树算法Kruskal算法Prim算法 最短路径算法Dijkstra算法BellmanFord算法FloydWarshall算法 全部代码链接 前言 图是真的难&#xff0c;即使这些我都学过一遍&#xff0c;再看还是要顺一下过程&#xff1b;说明方…...

idea Springboot 教师标识管理系统开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 教师标识管理系统是一套完善的信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统 具有完整的源代码和数据库&…...

2023-9-30 JZ36 二叉搜索树与双向链表

题目链接&#xff1a;二叉搜索树与双向链表 import java.util.*; /** public class TreeNode {int val 0;TreeNode left null;TreeNode right null;public TreeNode(int val) {this.val val;}} */ public class Solution {TreeNode pre null;public TreeNode Convert(Tree…...

在windows的ubuntu LTS中安装及使用EZ-InSAR进行InSAR数据处理

EZ-InSAR&#xff08;曾被称为MIESAR&#xff0c;即Matlab界面用于易于使用的合成孔径雷达干涉测量&#xff09;是一个用MATLAB编写的工具箱&#xff0c;用于通过易于使用的图形用户界面&#xff08;GUI&#xff09;进行干涉合成孔径雷达&#xff08;InSAR&#xff09;数据处理…...

腾讯mini项目-【指标监控服务重构】2023-08-25

今日已办 traefik proxy jaeger Prometheus prometheus | Prometheus 配置完依然无法实现 web-url的前缀访问【待解决】 Set span storage type : elasticsearch services:elasticsearch:image: elasticsearch:7.17.12container_name: elasticsearchnetworks:- backend # …...

数据挖掘(1)概述

一、数据仓库和数据挖掘概述 1.1 数据仓库的产生 数据仓库与数据挖掘&#xff1a; 数据仓库和联机分析处理技术(存储)。数据挖掘&#xff1a;在大量的数据中心挖掘感兴趣的知识、规则、规律、模式、约束(分析)。数据仓库用于决策分析&#xff1a; 数据仓库&#xff1a;是在数…...

YApi Pro

1.介绍 说明&#xff1a;YApi Pro 是一款高效、易用、功能强大的 API 管理平台&#xff0c;旨在为开发、产品、测试人员提供更优雅的接口管理服务。它可以帮助开发者轻松创建、发布、维护 API&#xff0c;同时为用户提供了优秀的交互体验&#xff0c;开发人员可以更加高效地完…...

AUTOSAR RTE介绍(更新版230925)

RTE是什么 AUTOSAR RTE(Run Time Environment)实现了AUTOSAR系统中的虚拟功能总线(VFB),提供了SWC(Software Component)之间的访问接口和SWC对于BSW资源的访问接口。RTE为SWC中的Runnable提供与其他SWC或者BSW模块通信的接口,RTE将Runnable映射到OS Task中,并且管理Runna…...

深度学习笔记_1、定义神经网络

1、使用了PyTorch的nn.Module类来定义神经网络模型;使用nn.Linear来创建全连接层。(CPU) import torch.nn as nn import torch.nn.functional as F from torchsummary import summary# 定义神经网络模型 class Net(nn.Module):def __init__(self):super(Net, self).__init__()…...

【Java 进阶篇】MySQL 事务详解

在数据库管理中&#xff0c;事务是一组SQL语句的执行单元&#xff0c;它们被视为一个整体。事务的主要目标是保持数据库的一致性和完整性&#xff0c;即要么所有SQL语句都成功执行&#xff0c;要么所有SQL语句都不执行。在MySQL中&#xff0c;事务起到了非常重要的作用&#xf…...

Spring修炼之旅(3)自动装配与注解开发

一、自动装配说明 1.1概述 自动装配是使用spring满足bean依赖的一种方法 spring会在应用上下文中为某个bean寻找其依赖的bean。 1.2装配机制 Spring中bean有三种装配机制&#xff0c;分别是&#xff1a; 在xml中显式配置&#xff1b; 在java中显式配置&#xff1b; 隐式…...

嵌入式Linux应用开发-基础知识-第十六章GPIO和Pinctrl子系统的使用

嵌入式Linux应用开发-基础知识-第十六章GPIO和Pinctrl子系统的使用 第十六章 GPIO 和 Pinctrl 子系统的使用16.1 Pinctrl 子系统重要概念16.1.1 引入16.1.2 重要概念16.1.3 示例16.1.4 代码中怎么引用pinctrl 16.2 GPIO子系统重要概念16.2.1 引入16.2.2 在设备树中指定引脚16.2…...

Ubuntu系统下使用apt-get安装Mysql8

记录一下在Ubuntu20.04 64位系统下面使用apt-get方式安装mysql8关系型数据库 Centos下使用yum安装Mysql8&#xff08;Mysql5.7&#xff09;以及常见的配置和使用 首先肯定是检查下当前Ubuntu系统是否已经安装过mysql数据库 一般拿到新的云服务器是没有安装的 rootmyw:~# whe…...

jenkins联动显示或隐藏参数

1. 添加组件 Active Choices Plug-in 如jenkins无法联网&#xff0c;可在以下两个地址中下载插件&#xff0c;然后放到/home/jenkins/.jenkins/plugin下面重启jenkins即可 Active Choices Active Choices | Jenkins plugin 2. 效果如下&#xff1a; sharding为空时&#xf…...

Error: Activity class {xxx.java} does not exist

git切换到不同的branch之后&#xff0c;报下面的错误&#xff1a; Error: Activity class {xxx.java} does not exist 解决方案&#xff1a; 首先clean 然后会删除build目录 然后点击&#xff1a;Invalidate Caches Android Studio重启&#xff0c;然后重新build即可。...

保护模式阶段测试-模拟3环0环调用

保护模式阶段测试-模拟3环0环调用 最近又复习了一下保护模式相关的内容&#xff0c;然后打算搞个能够把段页的大部分知识能够串联起来的测试代码 最终想到的一个项目如下&#xff1a; 三环部分&#xff1a; 0.编写一个函数读取高2g的地址内容 1.通过设备通信到0环告诉0环我新…...

Dart笔记:stream_channel 包用法

标题1 标题2 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/133426961 【介绍】stream_channel是一个用…...

Java进阶必会JVM-深入浅出Java虚拟机

系列文章目录 送书第一期 《用户画像&#xff1a;平台构建与业务实践》 送书活动之抽奖工具的打造 《获取博客评论用户抽取幸运中奖者》 送书第二期 《Spring Cloud Alibaba核心技术与实战案例》 送书第三期 《深入浅出Java虚拟机》 文章目录 系列文章目录前言一、推荐书籍二…...

1200*B. Sorted Adjacent Differences(构造)

Problem - 1339B - Codeforces 解析&#xff1a; 题目要求每相邻两个值差的绝对值相等或递增。 先排序&#xff0c;可以想到我们先取两侧的数肯定相距最远&#xff0c;然后靠中心每次取两个数&#xff0c;这样符合题目要求。 直接遍历&#xff0c;先取的是答案靠后的数据&…...

恼人的TCP套接字部分发送成功场景

源起 以前就知道套接字有可能出现部分发送成功的可能&#xff0c;直到近段时间一个典型的使用场景触发了明确的此问题&#xff0c;才予以重视&#xff0c;比较深入地考虑解决这个问题的方案&#xff01; 分析 因为TCP的流式特征&#xff0c;如果出现部分发送成功&#xff0c…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...