C++ STL 中泛型算法:查找、排序、修改、统计、生成
- 1. algorithm 概述
- 1.1 常见分类与函数速览
- 1.2 实战技巧与性能建议
- 1.3 algorithm 小结
- 2. algorithm 常用函数
- 2.1 查找类算法(find 系列)
- 2.2 排序与重排算法
- 2.3 最值与比较类算法
- 2.4 修改类算法(复制 / 删除 / 替换)
- 2.5 集合与合并算法
- 2.6 变换与生成算法
- 2.7 数值算法(来自 numeric)
- 3. C++ 示例代码
- 3.1 常用组合技巧
- 3.2 algorithm 中20个函数
1. algorithm 概述
<algorithm> 是 C++ STL 里最强大、最常用的头文件之一,它提供了200 多个泛型算法,用于处理容器(如 vector, list, deque, array, map 等)的查找、排序、计数、修改等操作。这些算法全部基于迭代器,因此不仅能作用于 STL 容器,也能用于原生数组、指针区间。
C++ 的 <algorithm> 是 STL 的「灵魂」。
它让你不再需要手写 for 循环,而用函数式方式表达算法逻辑,既安全又高效。
💡 一条原则:能用算法的地方,就不要写 for。
1.1 常见分类与函数速览
| 分类 | 常用函数 |
|---|
| 查找 | find, find_if, any_of, all_of, none_of, count_if |
| 排序/重排 | sort, reverse, rotate, nth_element, shuffle |
| 修改 | copy, remove_if, replace_if, unique, fill, transform |
| 统计/最值 | count, accumulate, max_element, min_element, clamp |
| 生成 | iota, generate, fill, generate_n |
| 集合/合并 | merge, set_union, set_intersection, set_difference |
1.2 实战技巧与性能建议
| 技巧 | 说明 |
|---|
| ✅ 搭配 lambda 表达式 | 函数式写法简洁清晰 |
| ✅ 配合 erase-remove 惯用法 | 真正删除元素 |
| ✅ 对 vector 用 sort 替代 map 查找 | 可显著提高缓存局部性 |
| ✅ stable_sort 用于保持逻辑顺序 | UI 列表、日志排序等 |
| ⚠️ remove_if 不改变容器大小 | 必须 .erase() |
| ⚠️ 集合算法要求输入有序 | 否则结果错误 |
| ⚡ 算法与并行 STL | C++17 起可使用 std::execution::par 并行加速 |
1.3 algorithm 小结
| 分类 | 核心算法 | 典型用途 |
|---|
| 查找 | find, find_if | 搜索条件匹配项 |
| 排序 | sort, reverse | 数据排序与反转 |
| 修改 | remove_if, replace_if, transform | 批量修改元素 |
| 统计 | count, accumulate | 数据统计与求和 |
| 生成 | iota, generate | 创建序列或随机数据 |
| 合并 | merge, set_union | 合并多个有序数据 |
2. algorithm 常用函数
下面系统整理出最常用 + 最好用的函数(并分功能分类,含简短示例 )
2.1 查找类算法(find 系列)
这些算法用于在区间 [first, last) 中查找满足条件的元素
| 函数 | 作用 | 示例 |
|---|
std::find | 查找第一个等于指定值的元素 | auto it = std::find(v.begin(), v.end(), 3); |
std::find_if | 查找第一个满足条件的元素 | auto it = std::find_if(v.begin(), v.end(), [](int x){return x>3;}); |
std::find_if_not | 查找第一个不满足条件的元素 | auto it = std::find_if_not(v.begin(), v.end(), pred); |
std::any_of | 是否存在至少一个元素满足条件 | bool ok = std::any_of(v.begin(), v.end(), pred); |
std::all_of | 是否所有元素都满足条件 | bool ok = std::all_of(v.begin(), v.end(), pred); |
std::none_of | 是否所有元素都不满足条件 | bool ok = std::none_of(v.begin(), v.end(), pred); |
std::count | 统计指定值出现次数 | int n = std::count(v.begin(), v.end(), 3); |
std::count_if | 统计满足条件的元素数量 | int n = std::count_if(v.begin(), v.end(), [](int x){return x>5;}); |
💡 技巧:这些算法不修改容器,仅返回结果或迭代器,可安全用于 const 容器。
2.2 排序与重排算法
| 函数 | 作用 | 示例 |
|---|
std::sort | 快速排序(仅随机访问迭代器) | std::sort(v.begin(), v.end()); |
std::stable_sort | 稳定排序(保持相等元素相对顺序) | std::stable_sort(v.begin(), v.end()); |
std::partial_sort | 只对前 N 个元素排序 | std::partial_sort(v.begin(), v.begin()+3, v.end()); |
std::nth_element | 找出第 N 小的元素 | std::nth_element(v.begin(), v.begin()+n, v.end()); |
std::reverse | 反转区间 | std::reverse(v.begin(), v.end()); |
std::rotate | 左/右旋转 | std::rotate(v.begin(), v.begin()+1, v.end()); |
std::shuffle | 随机打乱元素 | std::shuffle(v.begin(), v.end(), std::mt19937{std::random_device{}()}); |
⚡ 小技巧:nth_element 常用于 快速求中位数 / Top-K 排序。
2.3 最值与比较类算法
| 函数 | 作用 | 示例 |
|---|
std::min / std::max | 返回两个值的最小 / 最大 | auto m = std::min(a,b); |
std::min_element / std::max_element | 找最小 / 最大元素迭代器 | auto it = std::max_element(v.begin(), v.end()); |
std::clamp | 限制值在 [low, high] 范围 | x = std::clamp(x, 0, 100); |
std::lexicographical_compare | 字典序比较两个区间 | if (lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())) ... |
2.4 修改类算法(复制 / 删除 / 替换)
| 函数 | 作用 | 示例 |
|---|
std::copy | 拷贝区间 | std::copy(a.begin(), a.end(), b.begin()); |
std::copy_if | 拷贝满足条件的元素 | std::copy_if(v.begin(), v.end(), out, pred); |
std::move | 移动元素 | std::move(a.begin(), a.end(), b.begin()); |
std::fill / std::fill_n | 填充固定值 | std::fill(v.begin(), v.end(), 0); |
std::replace / std::replace_if | 替换特定值或条件 | std::replace(v.begin(), v.end(), 1, 99); |
std::remove / std::remove_if | 删除元素(需配合 erase) | v.erase(remove_if(v.begin(), v.end(), pred), v.end()); |
std::unique | 删除连续重复元素(需配合 erase) | v.erase(unique(v.begin(), v.end()), v.end()); |
⚠️ remove 系列只是逻辑删除(移动不需要的元素到尾部),真正删除需要 v.erase(…)。
2.5 集合与合并算法
| 函数 | 作用 | 示例 |
|---|
std::merge | 合并两个有序区间 | std::merge(a.begin(), a.end(), b.begin(), b.end(), out.begin()); |
std::set_union | 并集 | set_union(a.begin(),a.end(),b.begin(),b.end(),out.begin()); |
std::set_intersection | 交集 | set_intersection(a.begin(),a.end(),b.begin(),b.end(),out.begin()); |
std::set_difference | 差集 | set_difference(a.begin(),a.end(),b.begin(),b.end(),out.begin()); |
std::set_symmetric_difference | 对称差 | set_symmetric_difference(a.begin(),a.end(),b.begin(),b.end(),out.begin()); |
🔧 要求:参与集合算法的区间必须是 有序 的!
2.6 变换与生成算法
| 函数 | 作用 | 示例 |
|---|
std::for_each | 对每个元素执行函数 | for_each(v.begin(),v.end(),[](auto &x){x*=2;}); |
std::transform | 对区间应用函数并输出 | transform(a.begin(),a.end(),b.begin(),[](int x){return x*2;}); |
std::generate / std::generate_n | 按函数生成元素 | generate(v.begin(),v.end(),rand); |
std::iota | 生成递增序列 | iota(v.begin(), v.end(), 1); |
2.7 数值算法(来自 numeric)
| 函数 | 作用 | 示例 |
|---|
std::accumulate | 求和或任意二元操作 | int sum = accumulate(v.begin(),v.end(),0); |
std::inner_product | 求向量内积 | auto dot = inner_product(a.begin(),a.end(),b.begin(),0); |
std::partial_sum | 局部累加 | partial_sum(v.begin(),v.end(),out.begin()); |
std::iota | 生成递增序列 | std::iota(v.begin(), v.end(), 0); |
3. C++ 示例代码
3.1 常用组合技巧
v.erase(std::remove_if(v.begin(), v.end(), [](int x){return x<0;}), v.end());
auto it = std::find_if(v.begin(), v.end(), [](int x){return x>10;});
if (it != v.end()) *it = 10;
int cnt = std::count_if(v.begin(), v.end(), [](int x){return x>5;});
bool hasEven = std::any_of(v.begin(), v.end(), [](int x){return x%2==0;});
3.2 algorithm 中20个函数
直接复制到工程中运行的完整示例文件:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <random>
#include <iterator> using namespace std;int main() {vector<int> v = {1, 2, 3, 4, 5, 3, 2, 1};cout << "原始数据: ";for (int x : v) cout << x << " ";cout << "\n\n";auto it = find(v.begin(), v.end(), 3);if (it != v.end()) cout << "find: 找到 3 在位置 " << distance(v.begin(), it) << "\n";it = find_if(v.begin(), v.end(), [](int x){ return x > 3; });if (it != v.end()) cout << "find_if: 第一个 >3 的是 " << *it << "\n";cout << "any_of: 是否存在偶数? " << boolalpha<< any_of(v.begin(), v.end(), [](int x){ return x % 2 == 0; }) << "\n";cout << "all_of: 是否所有元素 >0? "<< all_of(v.begin(), v.end(), [](int x){ return x > 0; }) << "\n";cout << "none_of: 是否所有元素都不是 10? "<< none_of(v.begin(), v.end(), [](int x){ return x == 10; }) << "\n";cout << "count: 值为 3 的数量 = " << count(v.begin(), v.end(), 3) << "\n";cout << "count_if: 大于 2 的数量 = "<< count_if(v.begin(), v.end(), [](int x){ return x > 2; }) << "\n";sort(v.begin(), v.end());cout << "sort: ";for (int x : v) cout << x << " ";cout << "\n";reverse(v.begin(), v.end());cout << "reverse: ";for (int x : v) cout << x << " ";cout << "\n";cout << "max_element: " << *max_element(v.begin(), v.end()) << "\n";cout << "min_element: " << *min_element(v.begin(), v.end()) << "\n";int sum = accumulate(v.begin(), v.end(), 0);cout << "accumulate: 总和 = " << sum << "\n";vector<int> seq(10);iota(seq.begin(), seq.end(), 1);cout << "iota: ";for (int x : seq) cout << x << " ";cout << "\n";sort(v.begin(), v.end());v.erase(unique(v.begin(), v.end()), v.end());cout << "unique: ";for (int x : v) cout << x << " ";cout << "\n";vector<int> v2 = {1, 2, 3, 4, 5, 6};v2.erase(remove_if(v2.begin(), v2.end(), [](int x){ return x % 2 == 0; }), v2.end());cout << "remove_if: 删除偶数后 -> ";for (int x : v2) cout << x << " ";cout << "\n";vector<int> v3 = {1, 2, 3, 4, 5};replace_if(v3.begin(), v3.end(), [](int x){ return x < 3; }, 0);cout << "replace_if: <3 的改为 0 -> ";for (int x : v3) cout << x << " ";cout << "\n";vector<int> v4(5);transform(v3.begin(), v3.end(), v4.begin(), [](int x){ return x * 2; });cout << "transform: 每个元素 *2 -> ";for (int x : v4) cout << x << " ";cout << "\n";cout << "for_each: 打印平方 -> ";for_each(v4.begin(), v4.end(), [](int x){ cout << x * x << " "; });cout << "\n";shuffle(seq.begin(), seq.end(), mt19937{random_device{}()});cout << "shuffle: ";for (int x : seq) cout << x << " ";cout << "\n";vector<int> a = {1, 3, 5};vector<int> b = {2, 4, 6};vector<int> merged;merge(a.begin(), a.end(), b.begin(), b.end(), back_inserter(merged));cout << "merge: ";for (int x : merged) cout << x << " ";cout << "\n";int x = 120;cout << "clamp: 限制 120 在 [0,100] -> " << clamp(x, 0, 100) << "\n";cout << "\n✅ 所有示例运行完毕。\n";return 0;
}