探索C++标准模板库中的强大算法,提升编程效率与代码质量
标准模板库(STL)提供了一系列强大的泛型算法,用于处理容器中的数据。这些算法通过迭代器与容器交互,提供高效的数据处理能力。
提示: STL算法通常定义在 <algorithm>
和 <numeric>
头文件中。
这些算法不会修改容器中的元素,主要用于搜索、计数和遍历操作。
在范围内查找特定元素或满足条件的元素。
#include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {1, 2, 3, 4, 5}; auto it = std::find(v.begin(), v.end(), 3); if (it != v.end()) { std::cout << "找到元素: " << *it << std::endl; } // 使用find_if查找第一个偶数 auto even = std::find_if(v.begin(), v.end(), [](int n) { return n % 2 == 0; }); if (even != v.end()) { std::cout << "第一个偶数是: " << *even << std::endl; } return 0; }
计算范围内满足特定条件的元素数量。
#include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {1, 2, 3, 4, 5, 3, 3}; int count_three = std::count(v.begin(), v.end(), 3); std::cout << "3出现的次数: " << count_three << std::endl; int count_even = std::count_if(v.begin(), v.end(), [](int n) { return n % 2 == 0; }); std::cout << "偶数的个数: " << count_even << std::endl; return 0; }
这些算法会修改容器中的元素,包括复制、替换、填充等操作。
将元素从一个范围复制到另一个范围,可选择满足条件的元素。
#include <algorithm> #include <vector> #include <iostream> #include <iterator> int main() { std::vector<int> src = {1, 2, 3, 4, 5}; std::vector<int> dest(5); // 复制整个范围 std::copy(src.begin(), src.end(), dest.begin()); // 复制满足条件的元素 std::vector<int> even_nums; std::copy_if(src.begin(), src.end(), std::back_inserter(even_nums), [](int n) { return n % 2 == 0; }); std::cout << "复制的偶数: "; for (int n : even_nums) std::cout << n << " "; return 0; }
对范围内的每个元素应用函数,并将结果存储到另一个范围。
#include <algorithm> #include <vector> #include <iostream> #include <cmath> int main() { std::vector<int> v = {1, 2, 3, 4, 5}; std::vector<int> squared; // 计算每个元素的平方 std::transform(v.begin(), v.end(), std::back_inserter(squared), [](int n) { return n * n; }); std::cout << "平方值: "; for (int n : squared) std::cout << n << " "; // 两个序列操作 std::vector<int> v1 = {1,2,3,4,5}; std::vector<int> v2 = {5,4,3,2,1}; std::vector<int> result; std::transform(v1.begin(), v1.end(), v2.begin(), std::back_inserter(result), std::plus<int>()); std::cout << "\n相加结果: "; for (int n : result) std::cout << n << " "; return 0; }
这些算法用于对容器中的元素进行排序、查找有序范围中的元素以及执行其他与排序相关的操作。
对范围内的元素进行排序,stable_sort 保持相等元素的相对顺序。
#include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {5, 3, 1, 4, 2}; // 默认升序排序 std::sort(v.begin(), v.end()); std::cout << "升序排序: "; for (int n : v) std::cout << n << " "; // 自定义排序函数 - 降序 std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; }); std::cout << "\n降序排序: "; for (int n : v) std::cout << n << " "; // 稳定排序 std::vector<std::pair<int, char>> pairs = {{1, 'a'}, {2, 'b'}, {1, 'c'}, {2, 'd'}}; std::stable_sort(pairs.begin(), pairs.end(), [](const auto& a, const auto& b) { return a.first < b.first; }); std::cout << "\n稳定排序结果: "; for (const auto& p : pairs) std::cout << p.first << p.second << " "; return 0; }
在已排序范围内执行二分查找操作,equal_range 返回匹配元素的范围。
#include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {1, 2, 3, 4, 5, 6, 7}; // 检查元素是否存在 bool found = std::binary_search(v.begin(), v.end(), 4); std::cout << "4是否在数组中: " << std::boolalpha << found; // 查找元素范围 auto range = std::equal_range(v.begin(), v.end(), 4); std::cout << "\n4的位置: [" << range.first - v.begin() << ", " << range.second - v.begin() << ")"; // 查找第一个不小于3的元素 auto low = std::lower_bound(v.begin(), v.end(), 3); std::cout << "\n第一个不小于3的元素: " << *low; // 查找第一个大于4的元素 auto up = std::upper_bound(v.begin(), v.end(), 4); std::cout << "\n第一个大于4的元素: " << *up; return 0; }
partial_sort 对范围的前N个元素排序,nth_element 重新排列元素使第n个元素处于正确位置。
#include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {9, 5, 2, 7, 1, 8, 3, 6, 4}; // 获取前3个最小元素 std::partial_sort(v.begin(), v.begin() + 3, v.end()); std::cout << "前3个最小元素: "; for (int i = 0; i < 3; ++i) std::cout << v[i] << " "; // 获取第5个元素(中位数) auto mid = v.begin() + v.size()/2; std::nth_element(v.begin(), mid, v.end()); std::cout << "\n中位数: " << *mid; // 划分前5个最大元素 std::partial_sort(v.begin(), v.begin() + 5, v.end(), [](int a, int b) { return a > b; }); std::cout << "\n前5个最大元素: "; for (int i = 0; i < 5; ++i) std::cout << v[i] << " "; return 0; }
根据谓词将元素分为两组,stable_partition 保持元素相对顺序。
提示: partition 常用于快速排序算法和按条件分组数据。
#include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // 将偶数移到前面 auto it = std::partition(v.begin(), v.end(), [](int n) { return n % 2 == 0; }); std::cout << "划分结果: "; std::cout << "\n偶数: "; for (auto i = v.begin(); i != it; ++i) std::cout << *i << " "; std::cout << "\n奇数: "; for (auto i = it; i != v.end(); ++i) std::cout << *i << " "; // 稳定划分 - 保持相对顺序 std::vector<int> v2 = {1, 2, 3, 4, 5, 6, 7, 8, 9}; auto it2 = std::stable_partition(v2.begin(), v2.end(), [](int n) { return n > 5; }); std::cout << "\n稳定划分(>5): "; for (int n : v2) std::cout << n << " "; return 0; }
这些算法用于执行数值计算操作,包括累加、内积、部分和等。
计算范围内元素的累加值或自定义二元操作的累积结果。
#include <numeric> #include <vector> #include <iostream> int main() { std::vector<int> v = {1, 2, 3, 4, 5}; // 基本求和 int sum = std::accumulate(v.begin(), v.end(), 0); std::cout << "元素总和: " << sum; // 自定义操作 - 乘积 int product = std::accumulate(v.begin(), v.end(), 1, [](int a, int b) { return a * b; }); std::cout << "\n元素乘积: " << product; // 字符串连接 std::vector<std::string> words = {"Hello", " ", "World", "!"}; std::string sentence = std::accumulate(words.begin(), words.end(), std::string("")); std::cout << "\n连接结果: " << sentence; // 计算平均值 double avg = std::accumulate(v.begin(), v.end(), 0.0) / v.size(); std::cout << "\n平均值: " << avg; return 0; }
计算两个范围的內积(点积)或自定义二元操作的累积结果。
提示: 除了数学应用,inner_product 还可用于计算两组数据的相关性。
#include <numeric> #include <vector> #include <iostream> int main() { std::vector<int> a = {1, 2, 3, 4, 5}; std::vector<int> b = {5, 4, 3, 2, 1}; // 基本点积 int dot = std::inner_product(a.begin(), a.end(), b.begin(), 0); std::cout << "点积: " << dot; // 自定义操作 - 计算曼哈顿距离 int manhattan = std::inner_product(a.begin(), a.end(), b.begin(), 0, std::plus<int>(), [](int x, int y) { return std::abs(x - y); }); std::cout << "\n曼哈顿距离: " << manhattan; // 计算欧几里得距离平方 int euclidean_sq = std::inner_product(a.begin(), a.end(), b.begin(), 0, std::plus<int>(), [](int x, int y) { int diff = x - y; return diff * diff; }); std::cout << "\n欧几里得距离平方: " << euclidean_sq; return 0; }
partial_sum 计算部分和,adjacent_difference 计算相邻元素的差。
#include <numeric> #include <vector> #include <iostream> #include <iterator> int main() { std::vector<int> v = {2, 3, 5, 7, 11}; std::vector<int> result; // 计算部分和 std::partial_sum(v.begin(), v.end(), std::back_inserter(result)); std::cout << "部分和: "; for (int n : result) std::cout << n << " "; // 重置结果向量 result.clear(); // 计算相邻差 std::adjacent_difference(v.begin(), v.end(), std::back_inserter(result)); std::cout << "\n相邻差: "; for (int n : result) std::cout << n << " "; // 自定义操作 - 计算斐波那契数列 std::vector<int> fib(10, 1); std::adjacent_difference(fib.begin(), fib.end()-1, fib.begin()+1, std::plus<int>()); std::cout << "\n斐波那契数列: "; for (int n : fib) std::cout << n << " "; return 0; }
用连续递增的值填充范围,从指定值开始。
#include <numeric> #include <vector> #include <iostream> int main() { std::vector<int> v(10); // 填充1到10 std::iota(v.begin(), v.end(), 1); std::cout << "1到10: "; for (int n : v) std::cout << n << " "; // 创建索引序列 std::vector<size_t> indices(5); std::iota(indices.begin(), indices.end(), 0); std::cout << "\n索引序列: "; for (size_t i : indices) std::cout << i << " "; // 生成字母序列 std::vector<char> letters(26); std::iota(letters.begin(), letters.end(), 'A'); std::cout << "\n大写字母: "; for (char c : letters) std::cout << c << " "; return 0; }
实际应用场景中算法的综合使用案例。
#include <iostream> #include <vector> #include <algorithm> #include <numeric> int main() { // 1. 创建数据集 std::vector<int> data = {7, 3, 5, 1, 9, 2, 8, 4, 6}; // 2. 排序数据 std::sort(data.begin(), data.end()); std::cout << "排序后: "; for (int n : data) std::cout << n << " "; // 3. 查找中位数 auto mid = data.begin() + data.size()/2; std::nth_element(data.begin(), mid, data.end()); std::cout << "\n中位数: " << *mid; // 4. 移除小于5的元素 auto new_end = std::remove_if(data.begin(), data.end(), [](int n) { return n < 5; }); data.erase(new_end, data.end()); std::cout << "\n大于等于5的元素: "; for (int n : data) std::cout << n << " "; // 5. 计算平均值 double avg = std::accumulate(data.begin(), data.end(), 0.0) / data.size(); std::cout << "\n平均值: " << avg; // 6. 查找最大值和最小值 auto minmax = std::minmax_element(data.begin(), data.end()); std::cout << "\n最小值: " << *minmax.first; std::cout << "\n最大值: " << *minmax.second; return 0; }
#include <iostream> #include <vector> #include <algorithm> struct Student { std::string name; int score; Student(std::string n, int s) : name(n), score(s) {} bool operator<(const Student& other) const { return score < other.score; } }; int main() { std::vector<Student> students = { {"Alice", 85}, {"Bob", 76}, {"Charlie", 92}, {"David", 68} }; // 按分数排序 std::sort(students.begin(), students.end()); std::cout << "按分数排序:\n"; for (const auto& s : students) { std::cout << s.name << ": " << s.score << "\n"; } // 查找分数大于80的学生 auto it = std::find_if(students.begin(), students.end(), [](const Student& s) { return s.score > 80; }); std::cout << "\n分数大于80的学生:\n"; while (it != students.end()) { std::cout << it->name << ": " << it->score << "\n"; it = std::find_if(std::next(it), students.end(), [](const Student& s) { return s.score > 80; }); } // 计算平均分 int total = std::accumulate(students.begin(), students.end(), 0, [](int sum, const Student& s) { return sum + s.score; }); double average = static_cast<double>(total) / students.size(); std::cout << "\n平均分: " << average; return 0; }