图海寻径——图相关算法的奇幻探索之旅
一、图的表示
1. 邻接矩阵 (Adjacency Matrix)
#include <iostream>
#include <vector>
#include <queue>
#include <limits>using namespace std;class GraphMatrix {
private:int numVertices;vector<vector<int>> adjMatrix;const static int INFINITY = numeric_limits<int>::max();public:GraphMatrix(int vertices) : numVertices(vertices), adjMatrix(vertices, vector<int>(vertices, INFINITY)) {}void addEdge(int u, int v, int weight) {if (u >= 0 && u < numVertices && v >= 0 && v < numVertices) {adjMatrix[u][v] = weight;adjMatrix[v][u] = weight; // 如果是无向图,则需要双向设置}}void BFS(int startVertex);void DFSUtil(int vertex, vector<bool>& visited);void DFS();
};void GraphMatrix::BFS(int startVertex) {vector<bool> visited(numVertices, false);queue<int> q;visited[startVertex] = true;q.push(startVertex);while (!q.empty()) {int current = q.front();cout << "Visited " << current << endl;q.pop();for (int i = 0; i < numVertices; ++i) {if (adjMatrix[current][i] != INFINITY && !visited[i]) {visited[i] = true;q.push(i);}}}
}void GraphMatrix::DFSUtil(int vertex, vector<bool>& visited) {visited[vertex] = true;cout << "Visited " << vertex << endl;for (int i = 0; i < numVertices; ++i) {if (adjMatrix[vertex][i] != INFINITY && !visited[i])DFSUtil(i, visited);}
}void GraphMatrix::DFS() {vector<bool> visited(numVertices, false);for (int i = 0; i < numVertices; ++i)if (!visited[i])DFSUtil(i, visited);
}
2. 邻接表 (Adjacency List)
#include <iostream>
#include <vector>
#include <list>
#include <queue>using namespace std;class GraphList {
private:int numVertices;vector<list<pair<int, int>>> adjLists;public:GraphList(int vertices) : numVertices(vertices), adjLists(vertices) {}void addEdge(int u, int v, int weight) {adjLists[u].push_back(make_pair(v, weight));adjLists[v].push_back(make_pair(u, weight)); // 如果是无向图,则需要双向添加}void BFS(int startVertex);void DFSUtil(int vertex, vector<bool>& visited);void DFS();
};void GraphList::BFS(int startVertex) {vector<bool> visited(numVertices, false);queue<int> q;visited[startVertex] = true;q.push(startVertex);while (!q.empty()) {int current = q.front();cout << "Visited " << current << endl;q.pop();for (auto& edge : adjLists[current]) {int neighbor = edge.first;if (!visited[neighbor]) {visited[neighbor] = true;q.push(neighbor);}}}
}void GraphList::DFSUtil(int vertex, vector<bool>& visited) {visited[vertex] = true;cout << "Visited " << vertex << endl;for (auto& edge : adjLists[vertex]) {int neighbor = edge.first;if (!visited[neighbor])DFSUtil(neighbor, visited);}
}void GraphList::DFS() {vector<bool> visited(numVertices, false);for (int i = 0; i < numVertices; ++i)if (!visited[i])DFSUtil(i, visited);
}
二、图的遍历算法
(一)深度优先搜索(DFS)
- 核心原理
- 以深度优先为策略,从起始顶点出发,沿着一条路径持续深入探索,直至无法继续或达成特定条件(如找到目标顶点)。随后回溯到前一步,继续探寻其他未访问路径,直至遍历完起始顶点所在连通分量的所有顶点。若图中存在未访问顶点,则选取其一作为新起始点,重复上述流程,直至整个图的所有顶点均被访问。
- 实现方式
- 递归实现:在递归函数中,首先标记当前顶点已访问,接着遍历其邻接顶点,对未访问的邻接顶点递归调用 DFS 函数。以下是使用邻接表存储图的递归 DFS 代码:
class GraphDFS {
private:vector<bool> visited;void DFSUtil(Graph& graph, int v) {visited[v] = true;cout << v << " ";for (const Edge& edge : graph.adjList[v]) {int neighbor = edge.to;if (!visited[neighbor]) {DFSUtil(graph, neighbor);}}}public:void DFS(Graph& graph) {visited.resize(graph.numVertices, false);for (int i = 0; i < graph.numVertices; ++i) {if (!visited[i]) {DFSUtil(graph, i);}}}
};
- 应用场景
- 图的连通性检测:执行一次 DFS 遍历,若所有顶点均能被访问到,则图是连通的;反之则不连通。
- 连通分量求解:多次调用 DFS,每次从一个未访问顶点启动,可获取图的各个连通分量。
- 迷宫探索:将迷宫建模为图,迷宫中的格子作为顶点,相邻格子间的通道作为边,DFS 可用于找寻从迷宫入口到出口的路径。
(二)广度优先搜索(BFS)
- 核心原理
- 从给定起始顶点开始,先访问该顶点,接着依次访问其所有未访问的邻接顶点,然后再访问这些邻接顶点的未访问邻接顶点,依此类推,按照层次顺序逐层向外拓展,直至遍历完图中的所有顶点。
- 实现方式
- 借助队列实现。首先将起始顶点入队并标记为已访问,然后循环取出队首顶点,访问其未访问邻接顶点并将这些邻接顶点入队,直至队列为空。以下是使用邻接表存储图的 BFS 示例代码:
class GraphBFS {
public:void BFS(Graph& graph, int start) {vector<bool> visited(graph.numVertices, false);queue<int> q;visited[start] = true;q.push(start);while (!q.empty()) {int current = q.front();q.pop();cout << current << " ";for (const Edge& edge : graph.adjList[current]) {int neighbor = edge.to;if (!visited[neighbor]) {visited[neighbor] = true;q.push(neighbor);}}}}
};
- 应用场景
- 无权图最短路径计算:在 BFS 遍历过程中,从起始顶点到其他顶点的路径长度即为它们在队列中被访问的层数,可用于求解无权图中两点间的最短路径长度及路径。
- 网络爬虫页面遍历:网络爬虫从起始页面出发,按照广度优先顺序遍历链接页面,能够优先抓取与起始页面距离较近的页面,确保信息获取的全面性和层次性。
三、最小生成树算法
(一)普里姆算法(Prim)
- 核心原理
- 从图中任选一个顶点作为起始点,构建初始的最小生成树集合。随后不断从剩余顶点中挑选与当前最小生成树集合相连且权值最小的边所对应的顶点,将其纳入最小生成树集合,持续该过程直至所有顶点均被加入。
- 实现细节
- 维护两个顶点集合,已在最小生成树中的顶点集合
U
和未在其中的顶点集合V - U
。使用数组key
记录每个顶点到当前最小生成树的最小权值边的权值,初始除起始顶点外均设为无穷大,同时用数组parent
记录每个顶点在最小生成树中的父顶点。以下是使用邻接表存储图的 Prim 算法代码:
- 维护两个顶点集合,已在最小生成树中的顶点集合
class PrimMST {
public:int prim(Graph& graph, int start) {vector<bool> inMST(graph.numVertices, false);vector<int> key(graph.numVertices, INT_MAX);vector<int> parent(graph.numVertices, -1);key[start] = 0;for (int count = 0; count < graph.numVertices - 1; ++count) {int minKey = INT_MAX, minIndex = -1;for (int v = 0; v < graph.numVertices; ++v) {if (!inMST[v] && key[v] < minKey) {minKey = key[v];minIndex = v;}}inMST[minIndex] = true;for (const Edge& edge : graph.adjList[minIndex]) {int neighbor = edge.to;int weight = 1; // 如果是带权图,这里改成对应边的权值if (!inMST[neighbor] && weight < key[neighbor]) {key[neighbor] = weight;parent[neighbor] = minIndex;}}}int sumWeight = 0;for (int i = 1; i < graph.numVertices; ++i) {sumWeight += key[i]; // 累加最小生成树边的权值(这里简单示例,实际带权图边权计算更复杂)}return sumWeight;}
};
- 时间复杂度分析
- 若采用邻接矩阵存储图,时间复杂度为(O(n^2)),其中(n)为顶点数。若运用堆优化,时间复杂度可降至(O((n + m)log n)),其中(m)为边数。
(二)克鲁斯卡尔算法(Kruskal)
- 核心原理
- 首先将图中所有边按照权值从小到大排序,然后依次考察每条边。若选取某条边不会与已选边构成回路,则将其纳入最小生成树,直至选取了(n - 1)条边((n)为顶点数)。
- 实现细节
- 需要借助并查集数据结构判断边加入后是否形成回路。并查集用于维护顶点的连通性信息,初始每个顶点各自属于独立集合,加入边时判断边的两个顶点是否在同一集合,若不在则合并两个集合。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;// 边的数据结构
struct Edge {int src, dest, weight;
};// 比较函数,用于对边按照权重排序
bool compare(const Edge& a, const Edge& b) {return a.weight < b.weight;
}// 并查集 (Union-Find) 的类
class UnionFind {
private:vector<int> parent, rank;public:UnionFind(int size) : parent(size), rank(size, 0) {for (int i = 0; i < size; ++i)parent[i] = i;}// 查找操作,带有路径压缩int find(int x) {if (parent[x] != x)parent[x] = find(parent[x]); // 路径压缩return parent[x];}// 合并操作,带有按秩合并void unionSets(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX != rootY) {if (rank[rootX] > rank[rootY])parent[rootY] = rootX;else if (rank[rootX] < rank[rootY])parent[rootX] = rootY;else {parent[rootY] = rootX;rank[rootX]++;}}}
};// Kruskal 算法实现
void kruskalMST(vector<Edge>& edges, int V) {sort(edges.begin(), edges.end(), compare); // 按权重升序排序边UnionFind uf(V);vector<Edge> mst;for (auto& edge : edges) {int rootSrc = uf.find(edge.src);int rootDest = uf.find(edge.dest);if (rootSrc != rootDest) { // 如果不形成环,则加入最小生成树mst.push_back(edge);uf.unionSets(rootSrc, rootDest);}}cout << "Edges in the MST:" << endl;for (auto& e : mst)cout << e.src << " -- " << e.dest << " == " << e.weight << endl;
}int main() {int V = 4; // 顶点数vector<Edge> edges = {{0, 1, 10},{0, 2, 6},{0, 3, 5},{1, 3, 15},{2, 3, 4}};kruskalMST(edges, V);return 0;
}
- 时间复杂度分析
- 时间复杂度主要取决于边的排序操作,通常为(O(mlog m)),其中(m)为边数。在稀疏图中,由于边数相对较少,克鲁斯卡尔算法往往比普里姆算法更具效率。
四、最短路径算法
(一)迪杰斯特拉算法(Dijkstra)
- 核心原理
- 适用于带权有向图(权值非负)。从源点出发,逐步确定到其他顶点的最短路径。维护一个已确定最短路径的顶点集合
S
,对于不在S
中的顶点v
,记录从源点到v
的当前最短路径长度d[v]
。每次从不在S
中的顶点里选取d[v]
最小的顶点u
加入S
,并更新与u
相邻顶点的d[v]
值。
- 适用于带权有向图(权值非负)。从源点出发,逐步确定到其他顶点的最短路径。维护一个已确定最短路径的顶点集合
- 实现细节
- 初始化时,源点的
d
值设为(0),其余顶点设为无穷大。然后持续重复选取最小d
值顶点并更新相邻顶点d
值的操作,直至所有顶点均被加入S
。以下是使用邻接表存储图的 Dijkstra 算法代码:
- 初始化时,源点的
class DijkstraSP {
public:vector<int> dijkstra(Graph& graph, int source) {vector<int> dist(graph.numVertices, INT_MAX);vector<bool> visited(graph.numVertices, false);dist[source] = 0;for (int count = 0; count < graph.numVertices - 1; ++count) {int minDist = INT_MAX, minIndex = -1;for (int v = 0; v < graph.numVertices; ++v) {if (!visited[v] && dist[v] < minDist) {minDist = dist[v];minIndex = v;}}visited[minIndex] = true;for (const Edge& edge : graph.adjList[minIndex]) {int neighbor = edge.to;int weight = 1; // 如果是带权图,这里改成对应边的权值if (!visited[neighbor] && dist[minIndex] + weight < dist[neighbor]) {dist[neighbor] = dist[minIndex] + weight;}}}return dist;}
};
- 时间复杂度分析
- 若采用邻接矩阵存储图,时间复杂度为(O(n^2)),其中(n)为顶点数。若使用堆优化,时间复杂度可降为(O((n + m)log n)),其中
m
为边数。
- 若采用邻接矩阵存储图,时间复杂度为(O(n^2)),其中(n)为顶点数。若使用堆优化,时间复杂度可降为(O((n + m)log n)),其中
(二)弗洛伊德算法(Floyd)
- 核心原理
- 可计算出图中任意两个顶点之间的最短路径。基于动态规划思想,对于任意两个顶点(i)和(j),考虑是否经过中间顶点(k)来更新(i)到(j)的最短路径长度。
- 实现细节
- 使用二维数组
dist
存储顶点之间的最短路径长度。初始时,dist[i][j]
为图中(i)到(j)的直接边权值(若有边),否则为无穷大。然后通过三层循环,依次以每个顶点k
作为中间顶点更新dist[i][j]
的值。以下是使用邻接矩阵存储图的 Floyd 算法示例代码:
- 使用二维数组
class FloydSP {
public:vector<vector<int>> floyd(GraphMatrix& graph) {int n = graph.numVertices;vector<vector<int>> dist = graph.adjMatrix;for (int k = 0; k < n; ++k) {for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {if (dist[i][k]!= INT_MAX && dist[k][j]!= INT_MAX &&dist[i][k] + dist[k][j] < dist[i][j]) {dist[i][j] = dist[i][k] + dist[k][j];}}}}return dist;}
};
- 时间复杂度分析
- 时间复杂度为(O(n^3)),其中(n)为顶点数。由于时间复杂度较高,适用于顶点数较少的图或者对所有顶点对最短路径都有需求的场景。
五、拓扑排序算法
- 核心原理
- 针对有向无环图(DAG),拓扑排序旨在将图中所有顶点排成一个线性序列,使得对于图中的任意一条有向边((u, v)),在序列中(u)均排在(v)之前。
- 实现方式(基于入度表)
- 首先统计每个顶点的入度,将入度为(0)的顶点入队。然后循环取出队首顶点,将其输出到拓扑序列中,并将其所有邻接点的入度减(1),若某个邻接点入度变为(0),则将其入队,直至队列为空。若最终输出的顶点数小于图中顶点总数,则说明图中有环,不存在拓扑排序。以下是拓扑排序的代码:
#include <iostream>
#include <vector>
#include <queue>
using namespace std;// 边结构体,用于邻接表存储边的信息
struct Edge {int to; // 边指向的顶点Edge(int t) : to(t) {}
};// 图结构体,使用邻接表存储
class Graph {
public:int numVertices; // 顶点数量vector<vector<Edge>> adjList; // 邻接表Graph(int n) : numVertices(n), adjList(n) {}// 添加边(有向图示例)void addEdge(int from, int to) {adjList[from].push_back(Edge(to));}
};class TopologicalSort {
public:vector<int> topologicalSort(Graph& graph) {int n = graph.numVertices;// 用于记录每个顶点的入度vector<int> inDegree(n, 0);// 计算每个顶点的入度for (int i = 0; i < n; i++) {for (const Edge& edge : graph.adjList[i]) {inDegree[edge.to]++;}}queue<int> zeroDegreeQueue;// 将入度为0的顶点入队for (int i = 0; i < n; i++) {if (inDegree[i] == 0) {zeroDegreeQueue.push(i);}}vector<int> topologicalOrder;// 进行拓扑排序while (!zeroDegreeQueue.empty()) {int current = zeroDegreeQueue.front();zeroDegreeQueue.pop();topologicalOrder.push_back(current);// 更新相邻顶点的入度,并将入度变为0的顶点入队for (const Edge& edge : graph.adjList[current]) {inDegree[edge.to]--;if (inDegree[edge.to] == 0) {zeroDegreeQueue.push(edge.to);}}}// 若排序后的顶点数小于图中顶点总数,则说明图中有环,不存在拓扑排序if (topologicalOrder.size() < n) {cout << "图中存在环,无法进行拓扑排序" << endl;return {};}return topologicalOrder;}
};int main() {Graph graph(6);graph.addEdge(5, 2);graph.addEdge(5, 0);graph.addEdge(4, 0);graph.addEdge(4, 1);graph.addEdge(2, 3);graph.addEdge(3, 1);TopologicalSort ts;vector<int> result = ts.topologicalSort(graph);if (!result.empty()) {cout << "拓扑排序结果为: ";for (int vertex : result) {cout << vertex << " ";}cout << endl;}return 0;
}
相关文章:
图海寻径——图相关算法的奇幻探索之旅
一、图的表示 1. 邻接矩阵 (Adjacency Matrix) #include <iostream> #include <vector> #include <queue> #include <limits>using namespace std;class GraphMatrix { private:int numVertices;vector<vector<int>> adjMatrix;const st…...

亚马逊云科技re:Invent:生成式AI与全球布局
作为全球云计算和人工智能领域一年一度的顶级盛宴,亚马逊云科技2024 re:Invent全球大会吸引了超过6万名现场观众以及40多万名线上参会者。而大会上生成式AI的相关话题和内容,也成为了所有观众关注的焦点。 大会期间,亚马逊云科技全球服务副总…...
Android 因为混淆文件配置,打release包提示running R8问题处理
一、报错信息 Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in E:\workplace\xxxxxx\app\build\outputs\mapping\release\missing_rules.txt. Missing class org.mediakit.R$layout (refer…...

20241209给Ubuntu20.04系统的的交换分区增加为20GB的步骤
20241209给Ubuntu20.04系统的的交换分区增加为20GB的步骤 2024/12/9 21:10 缘起,编译中科创达的高通CM6125模块的Android10的时候,老报错。 编译环境可以编译荣品的RK3566的Android13/Buildroot。 以前荣品的RK3566的Android13的编译环境是可以编译通CM6…...

Centos7环境下nifi单机部署
Centos7环境下nifi单机部署 前言一、安装Nifi1.1 下载并解压1.2 修改配置文件 二、启动Nifi程序三、Nifi的简单使用3.1 文件移动3.2 本地文件传到HDFS 参考博客 前言 本以为在服务器上部署nifi很简单,跟着教程走就好,但是并没有成功,可能是因…...

如何通过轻易云实现金蝶云星空与旺店通数据集成
案例分享:柏为金蝶退料申请退料开单08.03 在企业的供应链管理中,数据的准确性和实时性至关重要。本文将重点介绍如何通过轻易云数据集成平台,将金蝶云星空的数据高效集成到旺店通旗舰奇门系统中,以实现柏为金蝶退料申请退料开单0…...

OSG开发笔记(三十七):OSG基于windows平台msvc2017x64编译器官方稳定版本OSG3.4.1搭建环境并移植Demo
若该文为原创文章,未经允许不得转载 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/144258047 各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究 长沙红胖子Qt…...

2024最新小猫咪PHP加密系统源码V1.4_本地API接口_带后台
2024最新小猫咪PHP加密系统源码V1.4_本地API接口_带后台 小猫咪PHP加密系统历时半年,它再一次迎来更新,更新加密算法(这应该是最后一次更新加密算法了,以后主要更新都在框架功能上面了),适配php56-php74&a…...
K8S OOM killer机制
当kubelet没来得及触发pod驱逐,使得节点内存耗尽时,将触发节点上的OOM killer机制; Linux上有个机制叫OOM killer(Out Of Memory killer),这个机制会在系统内存耗尽的情况下发挥作用,即根据一定…...

什么是绩效文化?
绩效文化是一种组织文化,它将绩效视为核心价值观,贯穿于组织的各个层面和活动之中。 一、绩效文化的内涵 目标导向 绩效文化强调组织成员都朝着共同的目标努力。这个目标通常是明确、可衡量的,如企业的年度利润目标、市场份额增长目标等。例…...

【人工智能-CV领域】对抗生成网络(GAN)与扩散模型全面解析与深度融合:实现AI生成能力的新突破
文章目录 了解更多AI内容生成模型概述对抗生成网络(GAN)的深度解析GAN的基本原理GAN的损失函数GAN的优势与挑战 扩散模型(Diffusion Model)的深入探讨扩散模型的基本原理扩散模型的损失函数扩散模型的优势与挑战 GAN与扩散模型的全…...
IT系统运维监控指标体系-持续完善中
分类指标名称定义说明指标类型采集频率统计数据频率计量单位数据精度应用注册用户数统计当前注册用户总数量统计类1分钟分钟、小时、日个整数应用在线用户数统计当前在线用户总数量统计类1分钟分钟、小时、日个整数应用日登录人数统计当日登录用户总数量统计类1分钟分钟、小时、…...
RPC设计--TcpAcceptor
TcpAcceptor 其功能较为简单,把套接字通信的一整套流程封装起来。在构造函数中就创建好连接套接字、设置好端口复用,等待accept,即自己封装socket 、 bind等函数调用 传入本地要监听的地址和端口,完成上述流程。 可提供getList…...

《Python数据分析:活用pandas库》学习笔记Day1:Panda DataFrame基础知识
Python数据分析:活用pandas库 Python强大易用,是数据处理和数据分析利器,而众多库的加持令其如虎添翼。Pandas就是其中一个非常流行的开源库,它可以确保数据的准确性,将数据可视化,还可以高效地操作大型数…...

【Go 基础】并发相关
并发相关 CAS CAS算法(Compare And Swap),是原⼦操作的⼀种,,CAS 算法是⼀种有名的⽆锁算法。⽆锁编程,即不使⽤锁的情况下实现多线程之间的变量同步。可⽤于在多线程编程中实现不被打断的数据交换操作,从…...
数据质量规则(Data Quality Rules)
数据质量规则(Data Quality Rules)是指用来确保数据的准确性、完整性、一致性和可用性的标准或逻辑规则。这些规则通常在数据集成、数据存储和数据分析过程中执行,以保证数据符合预期的业务需求或技术规范。 以下是数据质量规则的分类及其内…...
stm32延时
1. void delay_config(void) {SysTick->CTRL | SysTick_CTRL_CLKSOURCE_Msk; //时钟源为系统时钟168MHzSysTick->LOAD 167; //重载值为168-1,每1us溢出一次 }void delay_ms(u32 nTime) {nTime * 1000;SysTick->CTRL | SysTick_CTRL_ENABLE_Msk; //…...
工作随笔2024,12.9
1.关于connect重复连接,会导致当该信号发出时槽函数会执行对应的次数,所以在添 加init相关名称的函数要查看内部是否有connect,是否会造成重复连接. 2. 建议如果是唯一一个连接的,可以使用uni Que connection这个属性 3. 有关事…...
【PGCCC】 pg_query 6.0:使用 Postgres 自己的解析器解析、反解析和规范化 SQL 查询的 Ruby 库
pg_query 这个 Ruby 扩展使用实际的 PostgreSQL 服务器源来解析 SQL 查询并返回内部 PostgreSQL 解析树。 此外,该扩展允许您规范化查询(用 $n 替换常量值)并将这些规范化的查询再次解析为解析树。 当您构建此扩展时,它会构建 …...
18.Vue 3 + OpenLayers:实现添加全屏显示功能示例
前言 在地图应用中,全屏显示功能可以为用户提供更好的视觉体验和交互感受。本文将带大家实现一个基于 Vue 3 和 OpenLayers 的全屏显示地图功能,适合初学者或开发者快速上手。 项目准备 1. 项目搭建 如果尚未创建 Vue 3 项目,可以通过以下…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...