对 vector 排序不必自己写一层层比较。标准库在 <algorithm> 里提供 std::sort、std::find 等函数:它们吃的是一段迭代器 [first, last),不关心容器叫什么名字。本质是函数模板,要求这段区间上的元素能比较或能拷贝。累加一类运算在 <numeric>。迭代器本身见下一节迭代器;逐条查阅见标准库 <algorithm>。
区间约定
last 指向尾后位置,不指向有效元素,与 v.begin() / v.end() 以及范围 for 一致。写成 std::sort(v.begin(), v.end()) 就是对整个 v 排序。
sort
默认升序。第三参数可换成比较函数、函数对象或 lambda。sort 要求随机访问迭代器,所以 vector 可以、list 应使用成员 sort。默认不保证相等元素的相对次序;需要稳定次序时用 std::stable_sort。
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = {5, 1, 4, 2, 3};
std::sort(v.begin(), v.end());
for (int x : v) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}输出:
1 2 3 4 5 find 与 count
std::find 从左到右找第一个等于给定值的元素,找不到则返回 end()。std::count 统计出现次数。关联容器应使用成员 find,不要对整棵树做线性扫描。
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = {10, 20, 30, 20};
auto it = std::find(v.begin(), v.end(), 20);
if (it != v.end()) {
std::cout << *it << "\n"; // 首个 20
}
std::cout << std::count(v.begin(), v.end(), 20) << "\n";
return 0;
}输出:
20
2transform 与 accumulate
transform 把每个元素映射到另一段区间;输出区间必须已经有足够位置,或配合 std::back_inserter 边写边 push_back(见迭代器)。accumulate 从初值开始累加。
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
int main() {
std::vector<int> a{1, 2, 3};
std::vector<int> b(a.size()); // 先准备好与 a 一样长的空间
std::transform(a.begin(), a.end(), b.begin(), [](int x) { return x * x; });
for (int x : b) {
std::cout << x << " ";
}
std::cout << "\n" << std::accumulate(a.begin(), a.end(), 0) << "\n";
return 0;
}输出:
1 4 9
6常用算法一览
| 算法 | 作用 | 头文件 |
|---|---|---|
sort / stable_sort | 排序 | <algorithm> |
find / find_if | 线性查找 | <algorithm> |
count / count_if | 计数 | <algorithm> |
transform | 映射 | <algorithm> |
accumulate | 累加 | <numeric> |
min_element / max_element | 最值位置 | <algorithm> |
reverse | 反转区间 | <algorithm> |
算法不负责给容器分配存储。向空 vector 写结果前须 resize 或使用插入迭代器。按条件删除元素时,常用 remove 把要删的挪到尾部,再用 erase 真正缩短,见下一节。
本节说明了 sort 与 find 等算法的入门用法。下一节介绍迭代器:统一遍历与算法接口的纽带。