50 C++ STL模板库-算法库 algorithm

STL模板库------算法库 algorithm

文章目录

  • [STL模板库------算法库 algorithm](#STL模板库——算法库 algorithm)
    • 一、非修改序列操作(Non-modifying)
      • [1. `all_of`](#1. all_of)
      • [2. `any_of`](#2. any_of)
      • [3. `none_of`](#3. none_of)
      • [4. `for_each`](#4. for_each)
      • [5. `count`](#5. count)
      • [6. `count_if`](#6. count_if)
      • [7. `mismatch`](#7. mismatch)
      • [8. `find`](#8. find)
      • [9. `find_if`](#9. find_if)
      • [10. `find_if_not`](#10. find_if_not)
      • [11. `find_end`](#11. find_end)
      • [12. `find_first_of`](#12. find_first_of)
      • [13. `adjacent_find`](#13. adjacent_find)
      • [14. `search`](#14. search)
      • [15. `search_n`](#15. search_n)
    • 二、修改序列操作(Modifying)
      • [1. `copy`](#1. copy)
      • [2. `copy_n`](#2. copy_n)
      • [3. `copy_if`](#3. copy_if)
      • [4. `copy_backward`](#4. copy_backward)
      • [5. `move` (C++11)](#5. move (C++11))
      • [6. `move_backward`](#6. move_backward)
      • [7. `swap_ranges`](#7. swap_ranges)
      • [8. `transform`](#8. transform)
      • [9. `replace`](#9. replace)
      • [10. `replace_if`](#10. replace_if)
      • [11. `replace_copy`](#11. replace_copy)
      • [12. `replace_copy_if`](#12. replace_copy_if)
      • [13. `fill`](#13. fill)
      • [14. `fill_n`](#14. fill_n)
      • [15. `generate`](#15. generate)
      • [16. `generate_n`](#16. generate_n)
      • [17. `remove`](#17. remove)
      • [18. `remove_if`](#18. remove_if)
      • [19. `remove_copy`](#19. remove_copy)
      • [20. `remove_copy_if`](#20. remove_copy_if)
      • [21. `unique`](#21. unique)
      • [22. `unique_copy`](#22. unique_copy)
      • [23. `reverse`](#23. reverse)
      • [24. `reverse_copy`](#24. reverse_copy)
      • [25. `rotate`](#25. rotate)
      • [26. `rotate_copy`](#26. rotate_copy)
      • [27. `sample` (C++17)](#27. sample (C++17))
      • [28. `shift_left` / `shift_right` (C++20)](#28. shift_left / shift_right (C++20))
    • 三、排序与划分(Sorting/Partitioning)
      • [1. `sort`](#1. sort)
      • [2. `stable_sort`](#2. stable_sort)
      • [3. `partial_sort`](#3. partial_sort)
      • [4. `partial_sort_copy`](#4. partial_sort_copy)
      • [5. `is_sorted`](#5. is_sorted)
      • [6. `is_sorted_until`](#6. is_sorted_until)
      • [7. `partition`](#7. partition)
      • [8. `stable_partition`](#8. stable_partition)
      • [9. `partition_copy`](#9. partition_copy)
      • [10. `is_partitioned`](#10. is_partitioned)
      • [11. `partition_point`](#11. partition_point)
    • [四、二分搜索(Binary Search)](#四、二分搜索(Binary Search))
      • [1. `lower_bound`](#1. lower_bound)
      • [2. `upper_bound`](#2. upper_bound)
      • [3. `equal_range`](#3. equal_range)
      • [4. `binary_search`](#4. binary_search)
    • 五、堆操作(Heap)
      • [1. `make_heap`](#1. make_heap)
      • [2. `push_heap`](#2. push_heap)
      • [3. `pop_heap`](#3. pop_heap)
      • [4. `sort_heap`](#4. sort_heap)
      • [5. `is_heap`](#5. is_heap)
      • [6. `is_heap_until`](#6. is_heap_until)
    • 六、合并操作(Merge)
      • [1. `merge`](#1. merge)
      • [2. `inplace_merge`](#2. inplace_merge)
      • [3. `includes`](#3. includes)
      • [4. `set_union`](#4. set_union)
      • [5. `set_intersection`](#5. set_intersection)
      • [6. `set_difference`](#6. set_difference)
      • [7. `set_symmetric_difference`](#7. set_symmetric_difference)
    • 七、排列操作(Permutation)
      • [1. `next_permutation`](#1. next_permutation)
      • [2. `prev_permutation`](#2. prev_permutation)
      • [3. `is_permutation`](#3. is_permutation)
    • 八、数值操作(Numeric)
      • [1. `iota`](#1. iota)
      • [2. `accumulate`](#2. accumulate)
      • [3. `inner_product`](#3. inner_product)
      • [4. `adjacent_difference`](#4. adjacent_difference)
      • [5. `partial_sum`](#5. partial_sum)
      • [6. `reduce` (C++17)](#6. reduce (C++17))
      • [7. `transform_reduce` (C++17)](#7. transform_reduce (C++17))
      • [8. `inclusive_scan` (C++17)](#8. inclusive_scan (C++17))
      • [9. `exclusive_scan` (C++17)](#9. exclusive_scan (C++17))
    • 九、比较操作(Comparison)
      • [1. `equal`](#1. equal)
      • [2. `lexicographical_compare`](#2. lexicographical_compare)
      • [3. `lexicographical_compare_three_way` (C++20)](#3. lexicographical_compare_three_way (C++20))
    • 十、最值操作(Min/Max)
      • [1. `min` / `max` / `minmax`](#1. min / max / minmax)
      • [2. `min_element` / `max_element` / `minmax_element`](#2. min_element / max_element / minmax_element)
      • [3. `clamp` (C++17)](#3. clamp (C++17))
    • [十一、 `<numeric>` 与 `<algorithm>` 库的核心区别](#十一、 <numeric><algorithm> 库的核心区别)

这下算法都包含在标准库中的 <algorithm>头文件中
合理使用算法库可大幅提升代码效率和可读性,避免重复造轮子。

一、非修改序列操作(Non-modifying)

检查元素但不修改容器。

1. all_of

检查所有元素是否满足条件。

cpp 复制代码
std::vector<int> v = {2, 4, 6, 8};
bool allEven = std::all_of(v.begin(), v.end(), [](int i){ return i % 2 == 0; }); // true 

2. any_of

检查至少一个元素满足条件。

cpp 复制代码
bool hasFive = std::any_of(v.begin(), v.end(), [](int i){ return i == 5; }); // false 

3. none_of

检查无元素满足条件。

cpp 复制代码
bool noNegative = std::none_of(v.begin(), v.end(), [](int i){ return i < 0; }); // true 

4. for_each

对每个元素执行操作。

cpp 复制代码
std::for_each(v.begin(), v.end(), [](int& i){ i *= 2; }); // v变为 {4, 8, 12, 16}

5. count

统计匹配值的元素数量。

cpp 复制代码
int cnt = std::count(v.begin(), v.end(), 8); // cnt = 1 

6. count_if

按条件统计元素数量。

cpp 复制代码
int cntEven = std::count_if(v.begin(), v.end(), [](int i){ return i % 4 == 0; }); // 2 

7. mismatch

返回两序列首个不同元素的位置。

cpp 复制代码
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = {1, 4, 3};
auto p = std::mismatch(v1.begin(), v1.end(), v2.begin()); // p.first → 2, p.second → 4 

8. find

查找首个匹配值的元素。

cpp 复制代码
auto it = std::find(v.begin(), v.end(), 12); // 指向12的迭代器 

9. find_if

查找首个满足条件的元素。

cpp 复制代码
auto it = std::find_if(v.begin(), v.end(), [](int i){ return i > 10; }); // 指向12

10. find_if_not

查找首个不满足条件的元素。

cpp 复制代码
auto it = std::find_if_not(v.begin(), v.end(), [](int i){ return i < 10; }); // 指向12

11. find_end

在序列中查找子序列的最后一次出现。

cpp 复制代码
std::vector<int> main = {1,2,3,4,1,2,3};
std::vector<int> sub = {1,2,3};
auto it = std::find_end(main.begin(), main.end(), sub.begin(), sub.end()); // 指向第2个{1,2,3}

12. find_first_of

在序列中查找子序列中任意元素的首次出现。

cpp 复制代码
std::vector<int> main = {4,3,2,1};
std::vector<int> targets = {5,1,7};
auto it = std::find_first_of(main.begin(), main.end(), targets.begin(), targets.end()); // 指向1

13. adjacent_find

查找首对相邻重复元素。

cpp 复制代码
std::vector<int> v = {1,3,3,5,7};
auto it = std::adjacent_find(v.begin(), v.end()); // 指向第一个3

在序列中查找子序列的首次出现。

cpp 复制代码
auto it = std::search(main.begin(), main.end(), sub.begin(), sub.end()); // 指向第一个{1,2,3}

15. search_n

查找连续n个相同值的元素。

cpp 复制代码
std::vector<int> v = {1,2,2,2,3};
auto it = std::search_n(v.begin(), v.end(), 3, 2); // 指向连续3个2的起点 

二、修改序列操作(Modifying)

直接修改容器内容。

1. copy

复制序列到新位置。

cpp 复制代码
std::vector<int> src = {1,2,3}, dest(3);
std::copy(src.begin(), src.end(), dest.begin()); // dest = {1,2,3}

2. copy_n

精确复制n个元素。

cpp 复制代码
std::copy_n(src.begin(), 2, dest.begin()); // dest前2位 = {1,2}

3. copy_if

按条件复制元素。

cpp 复制代码
std::copy_if(src.begin(), src.end(), dest.begin(), [](int i){ return i%2==1; }); // {1,3}

4. copy_backward

从后向前复制(避免重叠覆盖)。

cpp 复制代码
std::vector<int> v = {1,2,3,4,5};
std::copy_backward(v.begin(), v.begin()+3, v.end()); // v变为 {1,2,1,2,3}

5. move (C++11)

移动元素(转移所有权)。

cpp 复制代码
std::vector<std::string> a = {"apple", "banana"}, b(2);
std::move(a.begin(), a.end(), b.begin()); // a为空,b = {"apple", "banana"}

6. move_backward

从后向前移动。

cpp 复制代码
std::vector<int> v = {1,2,3,4};
std::move_backward(v.begin(), v.begin()+2, v.end()); // v = {1,2,1,2}

7. swap_ranges

交换两序列内容。

cpp 复制代码
std::vector<int> a = {1,2}, b = {3,4};
std::swap_ranges(a.begin(), a.end(), b.begin()); // a={3,4}, b={1,2}

8. transform

对元素应用函数并存储结果。

cpp 复制代码
std::vector<int> v = {1,2,3}, result(3);
std::transform(v.begin(), v.end(), result.begin(), [](int i){ return i*2; }); // result = {2,4,6}

9. replace

替换指定值。

cpp 复制代码
std::vector<int> v = {1,2,3,2};
std::replace(v.begin(), v.end(), 2, 99); // v = {1,99,3,99}

10. replace_if

按条件替换值。

cpp 复制代码
std::replace_if(v.begin(), v.end(), [](int i){ return i<3; }, 0); // v = {0,0,3,0}

11. replace_copy

复制并替换值。

cpp 复制代码
std::vector<int> src = {1,2,3}, dest(3);
std::replace_copy(src.begin(), src.end(), dest.begin(), 2, 99); // dest = {1,99,3}

12. replace_copy_if

复制并按条件替换。

cpp 复制代码
std::replace_copy_if(src.begin(), src.end(), dest.begin(), [](int i){return i%2==1;}, 0); // dest={0,2,0}

13. fill

用指定值填充序列。

cpp 复制代码
std::vector<int> v(5);
std::fill(v.begin(), v.end(), 10); // v = {10,10,10,10,10}

14. fill_n

填充前n个元素。

cpp 复制代码
std::fill_n(v.begin(), 3, 5); // v = {5,5,5,10,10}

15. generate

用函数生成值填充序列。

cpp 复制代码
int n = 0;
std::generate(v.begin(), v.end(), [&n]{ return n++; }); // v = {0,1,2,3,4}

16. generate_n

生成前n个元素。

cpp 复制代码
std::generate_n(v.begin(), 3, []{ return 10; }); // v = {10,10,10,3,4}

17. remove

删除指定值(逻辑删除)。

cpp 复制代码
std::vector<int> v = {1,2,3,2};
auto end = std::remove(v.begin(), v.end(), 2); // v变为{1,3,?,?}, end指向3后一位 
v.erase(end, v.end()); // 物理删除 → {1,3}

18. remove_if

按条件删除元素。

cpp 复制代码
end = std::remove_if(v.begin(), v.end(), [](int i){ return i%2==0; });

19. remove_copy

复制时跳过指定值。

cpp 复制代码
std::vector<int> src = {1,2,3}, dest;
std::remove_copy(src.begin(), src.end(), std::back_inserter(dest), 2); // dest = {1,3}

20. remove_copy_if

复制时跳过满足条件的元素。

cpp 复制代码
std::remove_copy_if(src.begin(), src.end(), std::back_inserter(dest), [](int i){ return i<3; });

21. unique

删除连续重复元素。

cpp 复制代码
std::vector<int> v = {1,1,2,3,3};
auto end = std::unique(v.begin(), v.end()); // v = {1,2,3,?,?}
v.erase(end, v.end()); // {1,2,3}

22. unique_copy

复制时跳过连续重复。

cpp 复制代码
std::unique_copy(v.begin(), v.end(), std::back_inserter(dest)); // dest = {1,2,3}

23. reverse

反转序列顺序。

cpp 复制代码
std::vector<int> v = {1,2,3};
std::reverse(v.begin(), v.end()); // v = {3,2,1}

24. reverse_copy

复制并反转序列。

cpp 复制代码
std::reverse_copy(v.begin(), v.end(), std::back_inserter(dest)); // dest = {1,2,3}

25. rotate

循环左移序列。

cpp 复制代码
std::vector<int> v = {1,2,3,4};
std::rotate(v.begin(), v.begin()+2, v.end()); // v = {3,4,1,2} (以3为起点)

26. rotate_copy

复制并循环移动。

cpp 复制代码
std::rotate_copy(v.begin(), v.begin()+1, v.end(), std::back_inserter(dest)); 

27. sample (C++17)

从序列中随机抽样。

cpp 复制代码
std::vector<int> in = {1,2,3,4}, out;
std::sample(in.begin(), in.end(), std::back_inserter(out), 2, std::mt19937{std::random_device{}()});

28. shift_left / shift_right (C++20)

序列左右移位。

cpp 复制代码
std::vector<int> v = {1,2,3,4};
std::shift_left(v.begin(), v.end(), 1); // v = {2,3,4,0} (左移1位)

三、排序与划分(Sorting/Partitioning)

1. sort

升序排序。

cpp 复制代码
std::vector<int> v = {4,2,5,1};
std::sort(v.begin(), v.end()); // v = {1,2,4,5}

2. stable_sort

稳定排序(保持相等元素顺序)。

cpp 复制代码
std::stable_sort(v.begin(), v.end());

3. partial_sort

部分排序(前n个最小元素)。

cpp 复制代码
std::partial_sort(v.begin(), v.begin()+2, v.end()); // 前2位是 {1,2}

4. partial_sort_copy

复制并部分排序。

cpp 复制代码
std::vector<int> src = {4,2,5}, dest(2);
std::partial_sort_copy(src.begin(), src.end(), dest.begin(), dest.end()); // dest = {2,4}

5. is_sorted

检查序列是否已排序。

cpp 复制代码
bool sorted = std::is_sorted(v.begin(), v.end()); // false

6. is_sorted_until

查找首个破坏排序的元素。

cpp 复制代码
auto it = std::is_sorted_until(v.begin(), v.end()); // 指向5(若v={1,2,4,3})

7. partition

按条件划分序列(真值在前)。

cpp 复制代码
std::vector<int> v = {1,2,3,4};
auto p = std::partition(v.begin(), v.end(), [](int i){ return i%2==0; }); // v={4,2,3,1}, p指向3 

8. stable_partition

稳定划分(保持相对顺序)。

cpp 复制代码
auto p = std::stable_partition(v.begin(), v.end(), [](int i){ return i>2; }); // v={3,4,1,2}

9. partition_copy

复制时划分到两个容器。

cpp 复制代码
std::vector<int> even, odd;
std::partition_copy(v.begin(), v.end(), 
                std::back_inserter(even), 
                std::back_inserter(odd),
                [](int i){ return i%2==0; });

10. is_partitioned

检查序列是否被划分。

cpp 复制代码
bool part = std::is_partitioned(v.begin(), v.end(), [](int i){ return i>2; }); // true

11. partition_point

查找划分点。

cpp 复制代码
auto p = std::partition_point(v.begin(), v.end(), [](int i){ return i>2; }); // 指向1 

四、二分搜索(Binary Search)

要求序列已排序!

1. lower_bound

返回首个 ≥ 指定值的迭代器。

cpp 复制代码
std::vector<int> v = {1,2,4,5};
auto it = std::lower_bound(v.begin(), v.end(), 3); // 指向4 

2. upper_bound

返回首个 > 指定值的迭代器。

cpp 复制代码
it = std::upper_bound(v.begin(), v.end(), 4); // 指向5

3. equal_range

返回匹配值的范围 [lower_bound, upper_bound)

cpp 复制代码
auto [low, high] = std::equal_range(v.begin(), v.end(), 4); // [指向4, 指向5)

检查值是否存在。

cpp 复制代码
bool exists = std::binary_search(v.begin(), v.end(), 3); // false 

五、堆操作(Heap)

基于堆的优先队列。

1. make_heap

将序列转化为最大堆。

cpp 复制代码
std::vector<int> v = {3,1,4,2};
std::make_heap(v.begin(), v.end()); // v = {4,2,3,1}

2. push_heap

向堆中插入元素(需先push_back)。

cpp 复制代码
v.push_back(5);
std::push_heap(v.begin(), v.end()); // v = {5,4,3,1,2}

3. pop_heap

移除堆顶元素(移至容器尾)。

cpp 复制代码
std::pop_heap(v.begin(), v.end()); // 堆顶5移至末尾 → v = {4,2,3,1,5}
v.pop_back(); // 移除5 

4. sort_heap

堆排序(升序)。

cpp 复制代码
std::sort_heap(v.begin(), v.end()); // v = {1,2,3,4}

5. is_heap

检查是否为堆。

cpp 复制代码
bool isHeap = std::is_heap(v.begin(), v.end()); // false 

6. is_heap_until

查找首个破坏堆结构的元素。

cpp 复制代码
auto it = std::is_heap_until(v.begin(), v.end()); // 指向末尾(已是堆)

六、合并操作(Merge)

1. merge

合并两个有序序列。

cpp 复制代码
std::vector<int> v1 = {1,3}, v2 = {2,4}, dest(4);
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), dest.begin()); // dest={1,2,3,4}

2. inplace_merge

合并同一容器的两个有序子序列。

cpp 复制代码
std::vector<int> v = {1,3,2,4};
std::inplace_merge(v.begin(), v.begin()+2, v.end()); // v={1,2,3,4}

3. includes

检查一个序列是否包含另一个序列。

cpp 复制代码
bool contains = std::includes(dest.begin(), dest.end(), v1.begin(), v1.end()); // true 

4. set_union

求两个有序序列的并集。

cpp 复制代码
std::set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), dest.begin());

5. set_intersection

求两个有序序列的交集。

cpp 复制代码
std::set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), dest.begin());

6. set_difference

求差集(在v1中但不在v2中)。

cpp 复制代码
std::set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), dest.begin());

7. set_symmetric_difference

求对称差集(仅在一个序列中出现的元素)。

cpp 复制代码
std::set_symmetric_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), dest.begin());

七、排列操作(Permutation)

1. next_permutation

生成下一个字典序排列。

cpp 复制代码
std::vector<int> v = {1,2,3};
while (std::next_permutation(v.begin(), v.end())) {
    // 遍历所有排列:{1,3,2} → {2,1,3} → ...
}

2. prev_permutation

生成上一个字典序排列。

cpp 复制代码
std::prev_permutation(v.begin(), v.end());

3. is_permutation

检查一个序列是否为另一个的排列。

cpp 复制代码
bool isPerm = std::is_permutation(v1.begin(), v1.end(), v2.begin());

八、数值操作(Numeric)

需包含 <numeric>头文件,但常与算法库协同使用。

1. iota

用递增序列填充容器。

cpp 复制代码
std::vector<int> v(5);
std::iota(v.begin(), v.end(), 10); // v = {10,11,12,13,14}

2. accumulate

累加元素(可自定义操作)。

cpp 复制代码
int sum = std::accumulate(v.begin(), v.end(), 0); // 10+11+...=60 
int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());

3. inner_product

计算两序列内积(点积)。

cpp 复制代码
std::vector<int> a = {1,2}, b = {3,4};
int dot = std::inner_product(a.begin(), a.end(), b.begin(), 0); // 1*3 + 2*4 = 11

4. adjacent_difference

计算相邻元素的差。

cpp 复制代码
std::vector<int> src = {2,4,8}, result(3);
std::adjacent_difference(src.begin(), src.end(), result.begin()); // result = {2,2,4}

5. partial_sum

计算部分和(前缀和)。

cpp 复制代码
std::partial_sum(src.begin(), src.end(), result.begin()); // result = {2,6,14}

6. reduce (C++17)

并行累加(无序)。

cpp 复制代码
int sum = std::reduce(v.begin(), v.end());

7. transform_reduce (C++17)

先变换再累加。

cpp 复制代码
int sq_sum = std::transform_reduce(v.begin(), v.end(), 0, std::plus<>(),
                                [](int i){ return i*i; });

8. inclusive_scan (C++17)

并行前缀和(包含当前元素)。

cpp 复制代码
std::inclusive_scan(v.begin(), v.end(), result.begin());

9. exclusive_scan (C++17)

并行前缀和(不包含当前元素)。

cpp 复制代码
std::exclusive_scan(v.begin(), v.end(), result.begin(), 0);

九、比较操作(Comparison)

1. equal

比较两序列是否相等。

cpp 复制代码
bool same = std::equal(v1.begin(), v1.end(), v2.begin());

2. lexicographical_compare

字典序比较。

cpp 复制代码
bool less = std::lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end());

3. lexicographical_compare_three_way (C++20)

三路字典序比较。

cpp 复制代码
auto cmp = std::lexicographical_compare_three_way(v1.begin(), v1.end(), v2.begin(), v2.end());

十、最值操作(Min/Max)

1. min / max / minmax

返回最小/最大/两者。

cpp 复制代码
int m = std::min({5,3,8}); // 3

// 同时返回最小值和最大值
auto [minVal, maxVal] = std::minmax({5,3,8}); // minVal=3, maxVal=8

2. min_element / max_element / minmax_element

在序列中查找最值。

cpp 复制代码
// 查找序列中最小值位置 
auto it = std::min_element(vec.begin(),  vec.end()); 

// 查找序列中最大值位置 
auto it = std::max_element(vec.begin(),  vec.end()); 

// 同时查找最小值和最大值位置 
auto [min_it, max_it] = std::minmax_element(vec.begin(),  vec.end()); 

3. clamp (C++17)

将值限制在范围内。

cpp 复制代码
int clamped = std::clamp(10, 0, 5); // 返回值5

关键分类:

非修改操作(15个)、修改操作(28个)、排序划分(11个)、二分查找(4个)、堆操作(6个)、合并操作(7个)、排列操作(3个)、数值操作(9个)、比较操作(3个)、最值操作(8个)。

十一、 <numeric><algorithm> 库的核心区别

库/特性 <numeric> <algorithm>
核心目标 数值计算与统计分析 通用数据操作与容器管理
典型操作 累加、内积、前缀和、并行归约 排序、查找、复制、变换、逻辑判断
数学关联性 强(直接处理数值运算逻辑) 弱(关注元素操作,不涉及数学推导)
哲学差异 侧重数学语义的封装(如点积、统计计算) 侧重数据操作的抽象(如元素遍历、结构变换)
适用场景 数值密集型任务如科学计算、统计分析) 通用数据处理(如容器操作、业务逻辑)