
在C++标准模板库(STL)中,泛型算法是连接容器与算法的桥梁,它通过模板技术实现了对数据操作的抽象化。
泛型算法通过模板+迭代器实现容器无关性,其设计哲学可概括为:
迭代器分为5类,支持不同操作:
迭代器类型 | 支持操作 | 典型容器 |
|---|---|---|
输入迭代器 | 单向读取 | istream |
输出迭代器 | 单向写入 | ostream |
前向迭代器 | 读写+多遍遍历 | forward_list |
双向迭代器 | 双向移动 | list, set |
随机访问迭代器 | 随机访问+全算符支持 | vector, deque |
代码示例:迭代器遍历
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {1,2,3,4,5};
// 随机访问迭代器演示
for(auto it = nums.begin(); it != nums.end(); ++it) {
std::cout << *it << " ";
}
// 反向迭代器演示
for(auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {
std::cout << *rit << " ";
}
}
函数对象(Functor)通过重载operator()实现可调用性,分为:
代码示例:自定义谓词
struct IsEven {
bool operator()(int x) { return x % 2 == 0; }
};
// 使用示例
std::vector<int> nums = {1,2,3,4,5};
auto it = std::find_if(nums.begin(), nums.end(), IsEven());通过bind和mem_fn实现参数绑定:
#include <functional>
void add(int a, int b, int& result) {
result = a + b;
}
int main() {
int res;
auto func = std::bind(add, 10, 20, std::ref(res));
func(); // 执行后res=30
// 成员函数适配器
struct Foo { void bar(int x) {} };
Foo foo;
auto mem_func = std::mem_fn(&Foo::bar);
mem_func(foo, 42);
}算法 | 功能 | 时间复杂度 |
|---|---|---|
find | 查找元素 | O(n) |
count | 统计元素出现次数 | O(n) |
for_each | 遍历执行操作 | O(n) |
代码示例:统计偶数
int main() {
std::vector<int> nums = {1,2,3,4,5};
int even_count = std::count_if(
nums.begin(), nums.end(),
[](int x){ return x % 2 == 0; }
);
std::cout << "Even count: " << even_count;
}算法 | 功能 | 注意事项 |
|---|---|---|
transform | 元素转换 | 需要输出迭代器 |
replace | 元素替换 | 原地修改 |
remove | 逻辑删除元素 | 需配合erase使用 |
代码示例:元素转换
int main() {
std::vector<int> src = {1,2,3,4,5};
std::vector<int> dest;
// 使用back_inserter适配器
std::transform(
src.begin(), src.end(),
std::back_inserter(dest),
[](int x){ return x * 2; }
);
// 输出:2 4 6 8 10
for(auto n : dest) std::cout << n << " ";
}算法 | 稳定性 | 时间复杂度 |
|---|---|---|
sort | 不稳定 | O(n log n) |
stable_sort | 稳定 | O(n log n) ~ O(n²) |
partial_sort | 不稳定 | O(n log k) |
代码示例:稳定排序
struct Person {
int id;
std::string name;
};
int main() {
std::vector<Person> people = {{3,"Alice"},{1,"Bob"},{2,"Charlie"}};
// 按id稳定排序
std::stable_sort(
people.begin(), people.end(),
[](const Person& a, const Person& b) {
return a.id < b.id;
}
);
}通过函数对象实现算法策略的动态切换:
template<typename T>
class Sorter {
public:
void setStrategy(std::function<bool(T,T)> strategy) {
_strategy = strategy;
}
void sort(std::vector<T>& vec) {
std::sort(vec.begin(), vec.end(), _strategy);
}
private:
std::function<bool(T,T)> _strategy;
};
// 使用示例
Sorter<int> sorter;
sorter.setStrategy([](int a, int b) { return a > b; }); // 降序策略通过组合简单算法构建复杂流程:
int main() {
std::vector<int> data = {5,3,7,2,8,1};
// 组合操作:排序后去重
std::sort(data.begin(), data.end());
auto last = std::unique(data.begin(), data.end());
data.erase(last, data.end());
// 输出:1 2 3 5 7 8
for(auto n : data) std::cout << n << " ";
}算法类型 | 最佳情况 | 平均情况 | 最坏情况 |
|---|---|---|---|
线性搜索 | O(1) | O(n) | O(n) |
快速排序 | O(n log n) | O(n log n) | O(n²) |
归并排序 | O(n log n) | O(n log n) | O(n log n) |
reserve()std::nth_element替代部分排序性能对比示例
#include <chrono>
void benchmark() {
const int size = 1e6;
std::vector<int> v(size);
// 测试不同算法性能
auto t1 = std::chrono::high_resolution_clock::now();
std::sort(v.begin(), v.end());
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
std::cout << "Sort time: " << duration.count() << " μs\n";
}C++泛型算法通过模板和迭代器机制,实现了算法与容器的解耦,为开发者提供了强大的抽象能力。掌握以下关键点可显著提升开发效率:
using声明在模板编程中有着重要应用,如定义模板类型别名等。