material/program/c_cpp/STL/algorithms.md

10 KiB
Raw Blame History

STL算法

目录

非修改性算法

find

template <class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last, const T& value);
  • InputIterator输入迭代器类型表示要搜索的范围的起始和结束位置。
  • first指向范围的起始位置的迭代器。
  • last指向范围的结束位置的迭代器不包含
  • value要查找的目标值。
  • 返回值:如果找到目标值,返回指向该元素的迭代器;如果没有找到,则返回 last

注意事项

  1. 返回值的判断 如果未找到目标值,返回值是 last,通常需要通过比较返回值是否等于 last 来判断是否找到目标

  2. 自定义对象的比较 如果要在自定义对象中使用 std::find,需要重载 operator==,以便算法能够比较对象是否相等

  3. 性能 是线性查找算法,时间复杂度为 O(n),其中 n 是范围内的元素数量

  4. 范围的正确性 确保 first 和 last 指向的范围是有效的,并且 first 不大于 last

conut

template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type count(
    InputIterator first,
    InputIterator last,
    const T& value
);
  • InputIterator输入迭代器类型表示要搜索的范围的起始和结束位置。
  • first指向范围的起始位置的迭代器。
  • last指向范围的结束位置的迭代器不包含
  • value要统计的目标值。
  • 返回值:返回等于目标值的元素个数,类型为 iterator_traits<InputIterator>::difference_type

注意事项

  1. 返回值的判断 返回值类型是 iterator_traits<InputIterator>::difference_type,通常是与容器相关的整数类型 int size_t

  2. 自定义对象的比较 需要重载 operator==,以便算法能够比较对象是否相等

  3. 性能 是线性查找算法,时间复杂度为 O(n),其中 n 是范围内的元素数量

  4. 范围的正确性 确保 first 和 last 指向的范围是有效的,并且 first 不大于 last

用于在有序序列中查找是否存在某个值,基于二分查找的思想,时间复杂度为 O(log n)

只返回布尔值,表示是否找到目标值,如果需要找到目标值的位置,可以结合 std::lower_boundstd::upper_bound 使用

template <class ForwardIterator, class T>
bool binary_search(ForwardIterator first, ForwardIterator last, const T& value);
  • ForwardIterator正向迭代器类型表示要搜索的范围的起始和结束位置。
  • first指向范围的起始位置的迭代器。
  • last指向范围的结束位置的迭代器不包含
  • value要查找的目标值。
  • 返回值:如果找到目标值,返回 true否则返回 false。

还支持自定义比较函数

template <class ForwardIterator, class T, class Compare>
bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp);
  • Compare比较函数用于定义元素之间的大小关系。如果未提供会使用默认的 < 比较运算符

修改性算法

copy

用于将一个范围内的元素复制到另一个范围中,是一个线性算法,时间复杂度为 O(n)

template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result);
  • InputIterator输入迭代器类型表示要复制的源范围的起始和结束位置。
  • first指向源范围的起始位置的迭代器。
  • last指向源范围的结束位置的迭代器不包含
  • OutputIterator输出迭代器类型表示目标范围的起始位置。
  • result指向目标范围的起始位置的迭代器。
  • 返回值:返回指向目标范围结束位置的迭代器(即 result + (last - first)

replace

用于在指定范围内将所有等于某个特定值的元素替换为另一个值

template <class ForwardIterator, class T>
void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value);
  • ForwardIterator正向迭代器类型表示要操作的范围的起始和结束位置。
  • first指向范围的起始位置的迭代器。
  • last指向范围的结束位置的迭代器不包含
  • old_value:要被替换的旧值。
  • new_value:用于替换的新值。

如果需要更复杂的替换逻辑(例如基于条件的替换),可以结合 std::replace_if 使用,后者允许传入一个谓词函数来定义替换条件。

reverse

反转指定范围内的元素顺序,要求输入范围的迭代器是双向迭代器,即支持双向遍历

template <class BidirectionalIterator>
void reverse(BidirectionalIterator first, BidirectionalIterator last);
  • BidirectionalIterator双向迭代器类型表示要反转的范围的起始和结束位置。
  • first指向范围的起始位置的迭代器。
  • last指向范围的结束位置的迭代器(不包含)

排序算法

sort

指定范围内的元素进行排序,要求输入范围的迭代器是随机访问迭代器,是不稳定的排序算法,平均时间复杂度为 O(n log n)

template <class RandomAccessIterator>
void sort(RandomAccessIterator first, RandomAccessIterator last);
  • RandomAccessIterator随机访问迭代器类型表示要排序的范围的起始和结束位置
  • first指向范围的起始位置的迭代器
  • last指向范围的结束位置的迭代器不包含

此外std::sort 还支持自定义比较函数

template <class RandomAccessIterator, class Compare>
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);

stable-sort

是一个稳定排序算法,对指定范围内的元素进行排序,同时保证相等元素的相对顺序不变

template <class RandomAccessIterator>
void stable_sort(RandomAccessIterator first, RandomAccessIterator last);

template <class RandomAccessIterator, class Compare>
void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);
  • first 和 last随机访问迭代器分别指向要排序范围的起始位置和结束位置不包含
  • Compare可选的比较函数用于定义排序规则。如果未提供默认使用 < 运算符

如果有足够的额外内存,std::stable_sort 的时间复杂度为 O(n log n),内存不足,时间复杂度可能退化为 O(n log² n)

nth-element

用于部分排序序列,使得第 k 小的元素被放置到正确的位置,同时保证所有在它之前的元素都不大于它,所有在它之后的元素都不小于它,平均时间复杂度O(n),最坏时间复杂度O(n²)

template <class RandomIt>
void nth_element(RandomIt first, RandomIt nth, RandomIt last);

template <class RandomIt, class Compare>
void nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp);
  • first指向序列起始位置的随机访问迭代器。
  • nth指向序列中第 k 个位置的迭代器0-based index
  • last指向序列结束位置的迭代器。
  • comp可选自定义比较函数默认使用 std::less

不会完全排序整个序列,它只保证第 k 小的元素在正确的位置上 该算法的性能优于完全排序

数值算法

accumulate

用于计算指定范围内元素的累积和,时间复杂度为 O(n)

std::accumulate 从 first 开始,逐个处理范围内的元素,将每个元素与累积结果进行操作(默认为加法),并将最终结果返回

template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init);

template <class InputIterator, class T, class BinaryOperation>
T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation op);
  • InputIterator输入迭代器类型表示要操作的范围的起始和结束位置。
  • first指向范围的起始位置的迭代器。
  • last指向范围的结束位置的迭代器不包含
  • T累积结果的类型。
  • init初始值用于开始累积操作。
  • BinaryOperation可选二元操作函数用于定义累积操作。如果未提供默认使用加法操作 std::plus<T> 预定义函数符

inner-product

集合算法

set-difference

merge

其他算法

unique

用于移除序列中相邻的重复元素,并返回一个指向“新序列”结束位置的迭代器。它不会改变原序列的长度,而是将重复元素移动到序列末尾,并返回一个指向“有效部分”结束位置的迭代器。因此,通常需要结合容器的 erase 方法来真正移除重复元素,O(n)

template <class ForwardIterator>
ForwardIterator unique(ForwardIterator first, ForwardIterator last);

template <class ForwardIterator, class BinaryPredicate>
ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred);
  • ForwardIterator正向迭代器类型表示要操作的序列的起始和结束位置。
  • first指向序列起始位置的迭代器。
  • last指向序列结束位置的迭代器不包含
  • BinaryPredicate可选二元谓词函数用于定义两个元素是否相等。如果未提供默认使用 operator==

shuffle

随机打乱指定范围内元素的顺序

template <class RandomAccessIterator, class URNG>
void shuffle(RandomAccessIterator first, RandomAccessIterator last, URNG&& g);
  • first 和 last随机访问迭代器分别指向要打乱范围的起始位置和结束位置不包含
  • URNG均匀随机数生成器,例如 std::mt19937std::default_random_enginei
// 使用随机数生成器
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::mt19937 rng(seed);

    // 打乱顺序
    std::shuffle(vec.begin(), vec.end(), rng);