图海寻径——图相关算法的奇幻探索之旅
一、图的表示
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 项目,可以通过以下…...

04_掌握Python基础语句
学习完本篇内容,你将掌握以下技能: 掌握 Python 中的基础类型,包括整数、浮点数、布尔值、字符串等。掌握 Python 中的运算符,包括算术运算符、比较运算符、逻辑运算符、位运算符等。掌握 Python 中的语句,包括赋值语句、选择语句、循环语句等。掌握 Python 中的控制流语句…...

iOS如何自定义一个类似UITextView的本文编辑View
对于IOS涉及文本输入常用的两个View是UITextView和UITextField,一个用于复杂文本输入,一个用于简单文本输入,在大多数开发中涉及文本输入的场景使用这两个View能够满足需求。但是对于富文本编辑相关的开发,这两个View就无法满足自…...

【时时三省】(NIT计算机考试)Word的使用方法
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 一、软件简介 Microsoft Word,简称Word,是微软公司开发的一款文字处理软件,广泛应用于文档编辑、排版、打印等领域。无论是撰写论文、报告、简历…...

openjdk17 jvm加载class文件,解析字段和方法,C++源码展示
##构造方法ClassFileParser,parse_stream解析文件流 ClassFileParser::ClassFileParser(ClassFileStream* stream,Symbol* name,ClassLoaderData* loader_data,const ClassLoadInfo* cl_info,Publicity pub_level,TRAPS) :_stream(stream),_class_name(NULL),_load…...

驱动断链的研究
准备 source insight 从现在开始我们正式进入内核编程,但是很多内核里面的结构和类型是需要我们额外声明的,我们就需要一个工具来快速的阅读WIn内核源码。这里我贴出我所参考的博客 羽夏看Win系统内核——SourceInsight 配置 WRK - 寂静的羽夏 - 博客…...

在 Windows WSL 上部署 Ollama 和大语言模型:从镜像冗余问题看 Docker 最佳实践20241208
🛠️ 在 Windows WSL 上部署 Ollama 和大语言模型:从镜像冗余问题看 Docker 最佳实践 ⭐ 引言 随着大语言模型(LLM)和人工智能技术的迅猛发展,开发者们越来越多地尝试在本地环境中部署模型进行实验。 但部署过程中常…...

做题时HashSet、TreeSet、LinkedHashSet的选择
一、HashSet 此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。 代码: import java.util.HashSet; import java.util.LinkedHashSet; import ja…...

Manus手套动作捕捉AI训练灵巧手
随着人工智能(AI)和机器人技术的融合日益紧密,使用真实动作数据AI扩容训练机器人的方式正在被用于开发更富表现力的机器人。Manus手套凭借精准的动作捕捉技术和导出数据的强大兼容性,在灵巧手的研发和应用中发挥了重要作用。 手部…...

嵌入式驱动开发详解4(内核定时器)
文章目录 前言通用定时器系统节拍节拍数与时间转换基本框架定时器使用代码展示通用定时器特点 高精度定时器 前言 LInux内核定时器是一种基于未来时间点的计时方式,以当前时刻来启动的时间点,以未来的某一时刻为终止点。比如,现在是10点5分&…...

Linux:信号的预备和产生
引入: 比如当前快递小哥需要通知你下来取快递(产生信号),然后通过电话或短信告知了你(发送信号),但是当前你正在打游戏,所以你并不会马上去处理,但是你会记得这件事&…...