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

【C++ 进阶】泛型算法:概述

目录

一、泛型算法基础概念

1.1 什么是泛型算法?

1.2 核心设计原则

1.3 算法分类体系

1.4 与 STL 容器的关系

二、迭代器:泛型算法的 “钥匙”

2.1 迭代器类型

2.2 迭代器适配器

三、常用泛型算法分类与实战

3.1 非修改型算法(只读)

3.2 修改型算法

3.3 排序与搜索算法

四、算法的高阶应用与优化

4.1 自定义谓词(Predicate)

4.2 性能优化技巧

4.3 C++20 新特性:Ranges 库

五、典型应用场景

5.1 数据处理流水线

5.2 游戏对象管理 

5.3 GUI事件处理

六、 常见误区与解决方案

6.1 迭代器失效问题

6.2 算法与容器不匹配

七、总结

八、参考资料


在 C++ 编程中,算法是处理数据的核心工具。传统算法往往针对特定数据类型设计,缺乏复用性;而泛型算法(Generic Algorithms)通过模板技术实现类型无关化,可适配多种容器与数据类型,极大提升代码通用性与效率。

一、泛型算法基础概念

1.1 什么是泛型算法?

泛型算法是一类基于模板的通用函数,不依赖具体数据类型,而是通过迭代器(Iterator)操作容器元素。例如,std::find用于查找元素,既可作用于vector<int>,也能适配list<string>,只需传递对应容器的迭代器即可。具有以下显著特点:

  • 类型无关性:可作用于各种容器类型

  • 通用接口:统一使用迭代器作为访问接口

  • 高效实现:经过深度优化的经典算法实现

  • 可组合性:算法之间可灵活组合使用

1.2 核心设计原则

  • 类型无关性:通过模板参数推导数据类型(如T)。
  • 迭代器抽象:算法仅依赖迭代器接口(如*it取值、++it移动),不关心容器内部结构。
  • 复用性:一套算法适配多种容器(vector、list、deque等)。

1.3 算法分类体系

STL算法可分为六大类:

分类代表算法特性说明
非修改序列算法find, count, for_each不改变容器内容
修改序列算法copy, replace, reverse直接修改容器元素
排序相关算法sort, stable_sort元素排序和重组
数值算法accumulate, inner_product数学计算操作
集合算法set_union, set_difference集合运算
堆算法make_heap, push_heap堆结构操作

1.4 与 STL 容器的关系

泛型算法是 C++ 标准模板库(STL)的重要组成部分,与容器紧密协作:

  • 容器提供数据存储:如vector管理动态数组。
  • 算法提供操作逻辑:如std::sort对容器元素排序。
  • 迭代器架起桥梁:通过迭代器范围[first, last)指定算法作用区间(last指向末尾后一位)。

图示:泛型算法、容器与迭代器的协作关系

二、迭代器:泛型算法的 “钥匙”

2.1 迭代器类型

C++ 定义了 5 类迭代器,算法依需求选用:

类型

功能特性

典型应用算法

输入迭代器

单向读取(*it、++it)

std::find、std::for_each

输出迭代器

单向写入(*it = value)

std::copy

前向迭代器

单向读写(输入 + 输出功能结合)

std::list专用算法

双向迭代器

双向读写(--it支持逆向)

std::reverse

随机访问迭代器

随机定位(it[n]、it += n)

std::sort、std::binary_search

2.2 迭代器适配器

  • std::back_inserter:自动适配push_back,简化元素插入。
  • std::istream_iterator/std::ostream_iterator:绑定流对象,实现文件 / 控制台数据读写。

示例:使用std::back_insertervector插入元素

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main() {vector<int> v;auto inserter = back_inserter(v);  // 创建插入迭代器*inserter = 10;  // 等效于v.push_back(10)*inserter = 20;  for (int x : v) cout << x << " ";  // 输出: 10 20return 0;
}

三、常用泛型算法分类与实战

3.1 非修改型算法(只读)

  • 查找类:std::find、std::count
  • 判断类:std::all_of、std::any_of
  • 统计类:std::accumulate

示例:统计容器中偶数个数

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;void doubleValue(int& x) { x *= 2; }int main() {vector<int> v = {1, 2, 3};std::for_each(v.begin(), v.end(), doubleValue);for (int x : v) cout << x << " ";  // 输出: 2 4 6return 0;
}

3.2 修改型算法

  • 变换类:std::transform
  • 替换类:std::replace
  • 删除类:std::remove(需结合容器erase真正删除)

示例:将容器元素翻倍

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;void doubleValue(int& x) { x *= 2; }int main() {vector<int> v = {1, 2, 3};std::for_each(v.begin(), v.end(), doubleValue);for (int x : v) cout << x << " ";  // 输出: 2 4 6return 0;
}

3.3 排序与搜索算法

  • 排序:std::sort(快速排序)、std::stable_sort(稳定排序)
  • 二分查找:std::binary_search

示例:自定义比较函数排序结构体

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;struct Point {int x, y;
};bool compareByX(const Point& a, const Point& b) {return a.x < b.x;
}int main() {vector<Point> points = {{3, 4}, {1, 2}, {2, 3}};std::sort(points.begin(), points.end(), compareByX);for (const auto& p : points) {cout << "(" << p.x << ", " << p.y << ") ";}return 0;
}

四、算法的高阶应用与优化

4.1 自定义谓词(Predicate)

通过 lambda 表达式或函数对象定制算法逻辑,如std::sort的比较规则、std::find_if的查找条件。

4.2 性能优化技巧

  • 避免不必要的拷贝:使用std::move减少元素复制开销。
  • 选择合适的容器与算法:例如,std::list不适合std::sort(需随机访问迭代器),应改用std::list::sort。

4.3 C++20 新特性:Ranges 库

Ranges 库简化算法调用,支持惰性求值(延迟计算)。例如:

#include <iostream>
#include <ranges>
#include <vector>
using namespace std;int main() {vector<int> v = {1, 2, 3, 4, 5};auto result = v | views::filter([](int x) { return x % 2 == 0; }) | views::transform([](int x) { return x * 2; });for (int x : result) cout << x << " ";  // 输出: 4 8return 0;
}

五、典型应用场景

5.1 数据处理流水线

// 读取数据 -> 过滤 -> 变换 -> 统计 -> 输出
ifstream input("data.txt");
vector<Data> raw_data;// 读取阶段
Data temp;
while (input >> temp) {raw_data.push_back(temp);
}// 过滤阶段
auto new_end = std::remove_if(raw_data.begin(), raw_data.end(), [](const Data& d){ return d.value < 0; });
raw_data.erase(new_end, raw_data.end());// 变换阶段
std::transform(raw_data.begin(), raw_data.end(), raw_data.begin(),[](Data d){ d.value *= 2; return d; });// 统计阶段
int count = std::count_if(raw_data.begin(), raw_data.end(),[](const Data& d){ return d.category == "A"; });// 输出阶段
std::for_each(raw_data.begin(), raw_data.end(),[](const Data& d){ cout << d << endl; });

5.2 游戏对象管理 

class GameObject {
public:bool isActive() const { return m_active; }void update() { /* ... */ }
private:bool m_active = true;
};vector<GameObject> objects;// 批量更新活跃对象
std::for_each(objects.begin(), objects.end(),[](GameObject& obj){ if (obj.isActive()) obj.update(); });// 移除所有非活跃对象
auto new_end = std::remove_if(objects.begin(), objects.end(),[](const GameObject& obj){ return !obj.isActive(); });
objects.erase(new_end, objects.end());

5.3 GUI事件处理

vector<Event> event_queue;// 处理鼠标事件
auto it = std::remove_if(event_queue.begin(), event_queue.end(),[](const Event& e){return e.type != MOUSE_MOVE &&e.type != MOUSE_CLICK;});
event_queue.erase(it, event_queue.end());// 分派事件
std::for_each(event_queue.begin(), event_queue.end(),[](const Event& e){switch(e.type) {case MOUSE_MOVE: handle_move(e); break;case MOUSE_CLICK: handle_click(e); break;}});

六、 常见误区与解决方案

6.1 迭代器失效问题

  • 场景:容器插入 / 删除元素后,原有迭代器可能失效。
  • 解决:使用插入迭代器(如back_inserter)或及时更新迭代器。

6.2 算法与容器不匹配

例如:对list使用std::sort会编译错误,应改用list::sort。

误用std::remove

vector<int> v = {1, 2, 2, 3};
v.erase(std::remove(v.begin(), v.end(), 2), v.end());  // 移除所有值为2的元素

std::remove仅逻辑删除(移动元素),需配合erase真正释放空间:

七、总结

泛型算法通过模板与迭代器的结合,实现了高度抽象与复用,是 C++ 高效编程的基石。从基础查找排序到复杂自定义逻辑,掌握算法的使用场景与迭代器适配技巧,能大幅提升代码质量。结合 C++ 新特性(如 Ranges 库),更可进一步简化开发流程。后续可深入探索分区算法、堆操作等进阶内容,解锁更多编程可能。

八、参考资料

  •  《C++ Primer(第 5 版)》这本书是 C++ 领域的经典之作,对 C++ 的基础语法和高级特性都有深入讲解。
  • 《Effective C++(第 3 版)》书中包含了很多 C++ 编程的实用建议和最佳实践。
  • 《C++ Templates: The Complete Guide(第 2 版)》该书聚焦于 C++ 模板编程,而using声明在模板编程中有着重要应用,如定义模板类型别名等。
  • C++ 官方标准文档:C++ 标准文档是最权威的参考资料,可以查阅最新的 C++ 标准(如 C++11、C++14、C++17、C++20 等)文档。例如,ISO/IEC 14882:2020 是 C++20 标准的文档,可从相关渠道获取其详细内容。
  • :这是一个非常全面的 C++ 在线参考网站,提供了详细的 C++ 语言和标准库文档。
  • :该网站提供了系统的 C++ 教程,配有丰富的示例代码和清晰的解释,适合初学者学习和理解相关知识。
  • 《C++标准库(第2版)》Nicolai M. Josuttis 著

  • Effective STL Scott Meyers 著

  • C++ Core Guidelines:C++ Core Guidelines

  • C++ Reference:https://en.cppreference.com/w/


相关文章:

【C++ 进阶】泛型算法:概述

目录 一、泛型算法基础概念 1.1 什么是泛型算法&#xff1f; 1.2 核心设计原则 1.3 算法分类体系 1.4 与 STL 容器的关系 二、迭代器&#xff1a;泛型算法的 “钥匙” 2.1 迭代器类型 2.2 迭代器适配器 三、常用泛型算法分类与实战 3.1 非修改型算法&#xff08;只读…...

系统与网络安全------Windows系统安全(10)

资料整理于网络资料、书本资料、AI&#xff0c;仅供个人学习参考。 域与活动目录 域相关概念 域和域控制器 域&#xff08;Domain&#xff09; 集中管理网络中多台计算机的一种逻辑模式 有别于工作组的对等式管理 是组织与存储资源的核心管理单元 域控制器&#xff08;D…...

Linux vagrant 导入ubuntu到virtualbox

前言 vagrant 导入ubuntu虚拟机前提要求 安装 virtualbox 和vagrant<vagrant-disksize> (Linux 方式 Windows 方式)创建一键部署ubuntu虚拟机 /opt/vagrant 安装目录/opt/VirtualBox 安装目录/opt/ubuntu22/Vagrantfile (可配置网络IP,内存,cpu,磁盘及分区,启动项,…...

eSTK.me Cloud Enhance Server 笔记

eSTK.me Cloud Enhance Server 笔记 一、 概述 eSTK.me Cloud Enhance Server 是一个用 Go 语言编写的开源服务器&#xff0c;旨在处理 eSTK.me 远程 eUICC&#xff08;嵌入式通用集成电路卡&#xff09;的请求&#xff0c;例如配置文件下载和通知处理。该服务器主要针对 EST…...

C++ 用红黑树封装map/set

前言 一、源码结构分析 二、模拟实现map/set 2.1 套上KeyOfT 2.2 普通迭代器实现 2.3 const迭代器实现 2.4 解决key不能修改的问题 2.5 map的[]实现 2.6 map/set以及红黑树源码 2.6.1 RBTree.h 2.6.2 set.h 2.6.3 map.h 总结 前言 之前的文章讲解了红黑树的具体实…...

【资料分享】瑞芯微RK3506(3核ARM+Cortex-A7 + ARM Cortex-M0)工业核心板选型资料

核心板简介 创龙科技SOM-TL3506是一款基于瑞芯微RK3506J/RK3506B处理器设计的3核ARM Cortex-A7 + ARM Cortex-M0全国产工业核心板,主频高达1.5GHz。核心板CPU、ROM、RAM、电源、晶振等所有元器件均采用国产工业级方案,国产化率100%。 核心板通过邮票孔连接方式引出2x DSMC、…...

3.7 字符串基础

字符串 &#xff08;str&#xff09;&#xff1a;和列表用法基本一致 1.字符串的创建 -str转换(字符串&#xff0c;可用于将其他字符类型转换为字符串) -单引号 双引号 三引号 2.索引 3.字符串的切片 4.字符串的遍历 5.字符串的格式化 6.字符串的运算符 7.字符串的函数 #…...

量子计算未来的潜力和挑战

据麦肯锡预测&#xff0c;到 2035 年或 2040 年&#xff0c;量子计算市场规模可能增长至约 800 亿美元。目前&#xff0c;许多量子比特技术正竞相成为首台通用、无差错量子计算机的基础&#xff0c;但仍面临诸多挑战。 我们将探讨量子计算的未来前景、潜力&#xff0c;以及它对…...

机器学习项目二:帕金森病检测

目录 下载数据 一、导入相关包 二、数据加载 三、特征工程 四、构建模型 五、评估与可视化 六、程序流程 七、完整代码 一、导入相关包 # 导入库部分 import numpy as np # 数值计算基础库 import pandas as pd # 数据处理库 from sklearn.preprocessing import MinMaxS…...

LDAP渗透测试

LDAP渗透测试 1.LDAP协议概述2.LDAP写公钥3.暴力破解LDAP4.LDAP信息收集ldapdomaindumpwindapsearch工具ldapsearch 1.LDAP协议概述 LDAP&#xff08;Lightweight Directory Access Protocol&#xff0c;轻量目录访问协议&#xff09;是一种访问和管理目录服务的应用层协议&am…...

五笔输入法学习的抉择:86版 or 98版?(一场关于效率与传承的思辨)

新开直接98&#xff0c;纯粹高开&#xff1b;老版过渡艰辛自知&#x1f60b;。 笔记模板由python脚本于2025-04-14 19:22:22创建&#xff0c;本篇笔记适合喜好汉字衷情母语的coder翻阅。 【学习的细节是欢悦的历程】 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;…...

为您的 Web 应用选择最佳文档阅读器

为显示选择合适的文档查看器是开发 Web 应用过程中至关重要的一步。文档查看器应能在提供功能性的同时&#xff0c;确保用户体验的流畅性。 开发人员必须评估多种因素&#xff0c;以确保效率、性能和兼容性。本文将帮助您了解影响用户文档浏览体验成功与否的关键指标。 渲染质…...

微服务之protobuf:下载、语法和使用一站式教程

基本介绍 Protobuf全称 Protocol Buffer&#xff0c;是 Google 公司于2008年开源的一种语言无关、平台无关、可扩展的用于序列化结构化数据——类似于XML&#xff0c;但比XML更小、更快、更简单&#xff0c;它可用于&#xff08;数据&#xff09;通信协议、数据存储等。你只需…...

国产海光 DCU 资源监控脚本 + Promethues+grafana 深度解析

在当今数字化时代,对于服务器资源的高效监控与管理愈发重要。特别是在使用国产海光 DCU 的场景下,如何精准掌握其资源使用情况,成为了众多技术人员关注的焦点。本文将详细介绍一款国产海光 DCU 资源监控脚本,以及它与 Prometheus 和 Grafana 的结合使用,助力大家实现对 DC…...

Ollama调用多GPU实现负载均衡

文章目录 &#x1f4ca; 背景说明&#x1f6e0;️ 修改 systemd 服务配置1. 配置文件路径2. 编辑服务文件2. 重新加载配置并重启服务3. 验证配置是否成功 &#x1f4c8; 应用效果示例1. 调用单个70b模型2. 调用多个模型&#xff08;70b和32b模型&#xff09; 总结&#x1f4cc;…...

WebRTC实时通话EasyRTC嵌入式音视频通信SDK,构建智慧医疗远程会诊高效方案

一、方案背景 当前医疗领域&#xff0c;医疗资源分布不均问题尤为突出&#xff0c;大城市和发达地区优质医疗资源集中&#xff0c;偏远地区医疗设施陈旧、人才稀缺&#xff0c;患者难以获得高质量的医疗服务&#xff0c;制约医疗事业均衡发展。 EasyRTC技术基于WebRTC等先进技…...

深入理解计算机系统记录

在 C 语言中&#xff0c;struct&#xff08;结构体&#xff09;和 union&#xff08;联合体&#xff09;都是用来存储多个不同类型的数据成员&#xff0c;但它们在内存分配和数据存储方式上有显著区别。下面详细说明它们的主要区别&#xff1a; 1. 内存分配 结构体&#xff08;…...

【笔记】对抗训练-GAN

对抗训练-GAN 深度学习中 GAN 的对抗目标函数详解与最优解推导一、GAN 的基本对抗目标函数二、判别器与生成器的博弈目标三、判别器的最优解推导四、最优判别器的含义五、总结六、WGAN 的动机&#xff08;为后续铺垫&#xff09; 深度学习中 GAN 的对抗目标函数详解与最优解推导…...

(二十三)安卓开发中数据存储之Room详解

在安卓开发中&#xff0c;Room 是一个强大的本地数据库解决方案&#xff0c;它是 Android Jetpack 的一部分&#xff0c;基于 SQLite 构建&#xff0c;提供了更高层次的抽象。Room 简化了数据库操作&#xff0c;减少了样板代码&#xff0c;同时支持与 LiveData 和 ViewModel 的…...

AIoT 智变浪潮演讲实录 | 刘浩然:让硬件会思考:边缘大模型网关助力硬件智能革新

4 月 2 日&#xff0c;由火山引擎与英特尔联合主办的 AIoT “智变浪潮”技术沙龙在深圳成功举行&#xff0c;活动聚焦 AI 硬件产业的技术落地与生态协同&#xff0c;吸引了芯片厂商、技术方案商、品牌方及投资机构代表等 700 多位嘉宾参会。 会上&#xff0c;火山引擎边缘智能高…...

【Windows】系统安全移除移动存储设备指南:告别「设备被占用」弹窗

Windows系统安全移除移动存储设备指南&#xff1a;告别「设备被占用」弹窗 解决移动硬盘和U盘正在被占用无法弹出 一、问题背景 使用Windows系统时&#xff0c;经常遇到移动硬盘/U盘弹出失败提示「设备正在使用中」&#xff0c;即使已关闭所有可见程序。本文将系统梳理已验证…...

C++运算符重载全面总结

C运算符重载全面总结 运算符重载是C中一项强大的特性&#xff0c;它允许程序员为自定义类型定义运算符的行为。以下是关于C运算符重载的详细总结&#xff1a; 一、基本概念 1. 什么是运算符重载 运算符重载是指为自定义类型&#xff08;类或结构体&#xff09;重新定义或重…...

ArmSoM Sige5 CM5:RK3576 上 Ultralytics YOLOv11 边缘计算新标杆

在计算机视觉技术加速落地的今天&#xff0c;ArmSoM 正式宣布其基于 ​​Rockchip RK3576​​ 的旗舰产品 ​​Sige5 开发板​​ 和 ​​CM5 核心板​​ 全面支持 Ultralytics YOLOv11 模型的 RKNN 部署。这一突破标志着边缘计算领域迎来新一代高性能、低功耗的 AI 解决方案&am…...

【计算机网络】什么是路由?核心概念与实战详解

&#x1f4cc; 引言 路由&#xff08;Routing&#xff09;是互联网的“导航系统”&#xff0c;负责将数据包从源设备精准送达目标设备。无论是浏览网页、发送消息还是视频通话&#xff0c;背后都依赖路由技术。本文将用通俗类比技术深度的方式&#xff0c;解析路由的核心机制。…...

【ubuntu】linux开机自启动

目录 开机自启动&#xff1a; /etc/rc.loacl system V 使用/etc/rc*.d/系统运行优先级 遇到的问题&#xff1a; 1. Linux 系统启动阶段概述 方法1&#xff1a;/etc/rc5.d/ 脚本延时日志 方法二&#xff1a;使用 udev 规则来触发脚本执行 开机自启动&#xff1a; /etc/…...

dnf install openssl失败的原因和解决办法

网上有很多编译OpenSSL源码(3.x版本)为RPM包的文章&#xff0c;这些文章在安装RPM包时都是执行rpm -ivh openssl-xxx.rpm --nodeps --force 这个命令能在缺少依赖包的情况下能强行执行安装 其实根据Centos的文档&#xff0c;安装RPM包一般是执行yum install或dnf install。后者…...

Java 在人工智能领域的突围:从企业级架构到边缘计算的技术革新

一、Java AI 的底层逻辑&#xff1a;从语言特性到生态重构 在 Python 占据 AI 开发主导地位的当下&#xff0c;Java 正通过技术重构实现突围。作为拥有 30 年企业级开发经验的编程语言&#xff0c;Java 的核心优势在于强类型安全、内存管理能力和分布式系统支持&#xff0c;这…...

操作系统导论——第19章 分页:快速地址转换(TLB)

使用分页作为核心机制来实现虚拟内存&#xff0c;可能会带来较高的性能开销。使用分页&#xff0c;就要将内存地址空间切分成大量固定大小的单元&#xff08;页&#xff09;&#xff0c;并且需要记录这些单元的地址映射信息。因为这些映射信息一般存储在物理内存中&#xff0c;…...

计算机网络:流量控制与可靠传输机制

目录 基本概念 流量控制&#xff1a;别噎着啦&#xff01; 可靠传输&#xff1a;快递必达服务 传输差错&#xff1a;现实中的意外 滑动窗口 基本概念 换句话说&#xff1a;批量发货排队验收 停止-等待协议 SW&#xff08;发1份等1份&#xff09; 超时重传&#xff1a;…...

SaaS、Paas、IaaS、MaaS、BaaS五大云计算服务模式

科普版&#xff1a;通俗理解五大云计算服务模式 1. SaaS&#xff08;软件即服务&#xff09; 一句话解释&#xff1a;像“租用公寓”&#xff0c;直接使用现成的软件&#xff0c;无需操心维护。 案例&#xff1a;使用钉钉办公、在网页版WPS编辑文档。服务提供商负责软件更新和…...