10C++ Primer(第5版)

泛型算法

STL算法

迭代器算法lambda表达式

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第10章:泛型算法(Generic Algorithms)

一、导读

1.1 本章学习目标

第10章介绍C++标准库的泛型算法。本章核心目标:

  • 掌握常用算法:查找、排序、变换、计数
  • 理解迭代器在算法中的作用:算法如何通过迭代器操作容器
  • 学会使用lambda与算法配合:自定义算法行为
  • 了解算法的性能考虑:时间复杂度
  • 掌握数值算法:accumulate、inner_product

1.2 为什么本章如此重要

泛型算法是STL的核心组成部分。熟练使用这些算法能大大提高编程效率,避免重复造轮子。算法与迭代器的组合提供了强大的数据处理能力。

1.3 核心问题引导

为什么算法使用迭代器而不是直接操作容器?

find和find_if有什么区别?

sort和stable_sort有什么区别?

lambda表达式在算法中如何使用?


二、核心概念详解

10.1 查找算法

cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

int main() {
    std::vector<int> v = {5, 2, 8, 1, 9, 3, 7, 4, 6};
    
    // find
    auto it = std::find(v.begin(), v.end(), 5);
    if (it != v.end()) {
        std::cout << "Found 5 at position " << (it - v.begin()) << std::endl;
    }
    
    // find_if
    auto even = std::find_if(v.begin(), v.end(), [](int x) {
        return x % 2 == 0;
    });
    if (even != v.end()) {
        std::cout << "First even: " << *even << std::endl;
    }
    
    // count
    std::vector<int> nums = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
    int cnt = std::count(nums.begin(), nums.end(), 3);
    std::cout << "Count of 3: " << cnt << std::endl;
    
    // count_if
    int even_count = std::count_if(nums.begin(), nums.end(), [](int x) {
        return x % 2 == 0;
    });
    std::cout << "Even count: " << even_count << std::endl;
    
    // binary_search(需要已排序)
    std::sort(v.begin(), v.end());
    bool found = std::binary_search(v.begin(), v.end(), 5);
    std::cout << "Binary search 5: " << found << std::endl;
    
    return 0;
}

10.2 排序算法

cpp
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {5, 2, 8, 1, 9, 3, 7, 4, 6};
    
    // sort(不稳定排序)
    std::sort(v.begin(), v.end());
    for (int x : v) std::cout << x << " ";
    std::cout << std::endl;
    
    // 降序
    std::sort(v.begin(), v.end(), std::greater<int>());
    
    // 自定义排序
    std::sort(v.begin(), v.end(), [](int a, int b) {
        return a > b;
    });
    
    // stable_sort(稳定排序)
    std::stable_sort(v.begin(), v.end());
    
    // partial_sort(部分排序)
    std::partial_sort(v.begin(), v.begin() + 3, v.end());
    
    // nth_element(第n小的元素)
    std::nth_element(v.begin(), v.begin() + v.size()/2, v.end());
    std::cout << "Median: " << v[v.size()/2] << std::endl;
    
    // is_sorted
    bool sorted = std::is_sorted(v.begin(), v.end());
    std::cout << "Is sorted: " << sorted << std::endl;
    
    return 0;
}

10.3 变换算法

cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    
    // transform
    std::vector<int> doubled(v.size());
    std::transform(v.begin(), v.end(), doubled.begin(), [](int x) {
        return x * 2;
    });
    for (int x : doubled) std::cout << x << " ";
    std::cout << std::endl;
    
    // 原地变换
    std::transform(v.begin(), v.end(), v.begin(), [](int x) {
        return x * x;
    });
    for (int x : v) std::cout << x << " ";
    std::cout << std::endl;
    
    // replace
    std::replace(v.begin(), v.end(), 4, 40);
    
    // fill
    std::fill(v.begin(), v.end(), 0);
    
    // generate
    int n = 0;
    std::generate(v.begin(), v.end(), [&n]() { return n++; });
    
    // remove(不删除元素,只是移动)
    v = {1, 2, 3, 2, 4, 2, 5};
    auto new_end = std::remove(v.begin(), v.end(), 2);
    v.erase(new_end, v.end());  // 真正删除
    
    // unique(删除相邻重复)
    std::sort(v.begin(), v.end());
    new_end = std::unique(v.begin(), v.end());
    v.erase(new_end, v.end());
    
    for (int x : v) std::cout << x << " ";
    std::cout << std::endl;
    
    return 0;
}

10.4 数值算法

cpp
#include <iostream>
#include <vector>
#include <numeric>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    
    // accumulate
    int sum = std::accumulate(v.begin(), v.end(), 0);
    std::cout << "Sum: " << sum << std::endl;
    
    // accumulate with custom operation
    int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
    std::cout << "Product: " << product << std::endl;
    
    // inner_product
    std::vector<int> w = {2, 3, 4, 5, 6};
    int dot = std::inner_product(v.begin(), v.end(), w.begin(), 0);
    std::cout << "Dot product: " << dot << std::endl;
    
    // partial_sum
    std::vector<int> partial(v.size());
    std::partial_sum(v.begin(), v.end(), partial.begin());
    for (int x : partial) std::cout << x << " ";
    std::cout << std::endl;
    
    // adjacent_difference
    std::vector<int> diff(v.size());
    std::adjacent_difference(v.begin(), v.end(), diff.begin());
    for (int x : diff) std::cout << x << " ";
    std::cout << std::endl;
    
    return 0;
}

三、实战案例

3.1 数据处理管道

cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

struct Student {
    std::string name;
    int score;
};

int main() {
    std::vector<Student> students = {
        {"Alice", 90}, {"Bob", 85}, {"Charlie", 92},
        {"David", 78}, {"Eve", 88}, {"Frank", 95}
    };
    
    // 找出及格的学生
    std::vector<Student> passed;
    std::copy_if(students.begin(), students.end(), 
                 std::back_inserter(passed),
                 [](const Student &s) { return s.score >= 80; });
    
    // 按分数排序
    std::sort(passed.begin(), passed.end(),
              [](const Student &a, const Student &b) {
                  return a.score > b.score;
              });
    
    // 计算平均分
    double avg = std::accumulate(passed.begin(), passed.end(), 0.0,
                                 [](double sum, const Student &s) {
                                     return sum + s.score;
                                 }) / passed.size();
    
    std::cout << "Passed students (sorted):" << std::endl;
    for (const auto &s : passed) {
        std::cout << s.name << ": " << s.score << std::endl;
    }
    std::cout << "Average: " << avg << std::endl;
    
    return 0;
}

四、本章小结

第10章介绍了C++泛型算法:查找(find、binary_search)、排序(sort、stable_sort)、变换(transform、replace)、数值(accumulate、inner_product)。算法通过迭代器操作容器,与lambda配合非常强大。


五、思考与练习

思考题

为什么算法不直接操作容器,而是使用迭代器?

remove算法为什么不直接删除元素?

sort和stable_sort有什么区别?什么时候需要稳定排序?

accumulate的初始值有什么作用?

编程练习

使用算法实现一个简单的文本搜索引擎。

使用transform和accumulate计算加权平均。

实现一个自定义排序算法,按多个条件排序。


10/12泛型算法
0%