# STL算法 ## 目录 - [非修改性算法](#) - [find](#find) - [conut](#conut) - [二分查找](#binary-search) - [修改性算法](#) - [copy](#) - [replace](#):将指定范围内等于给定值的元素替换为新值 - [reverse](#):翻转序列 - [排序算法](#) - [sort](#) - [稳定排序](#stable-sort) - [第n大数](#nth-element) - [数值算法](#) - [accumulate](#):计算指定范围内元素的累积和 - [计算两个序列的内积](#inner-product) - [集合算法](#) - [两个有序序列的差集](#set-difference) - [将两个有序序列合并为一个有序序列](#merge) - [其他算法](#) - [去除相邻重复元素](#unique) - [随机打乱序列](#shuffle) ## 非修改性算法 ### find ``` template 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 typename iterator_traits::difference_type count( InputIterator first, InputIterator last, const T& value ); ``` + InputIterator:输入迭代器类型,表示要搜索的范围的起始和结束位置。 + first:指向范围的起始位置的迭代器。 + last:指向范围的结束位置的迭代器(不包含)。 + value:要统计的目标值。 + 返回值:返回等于目标值的元素个数,类型为 `iterator_traits::difference_type` __注意事项__ 1. 返回值的判断 返回值类型是 `iterator_traits::difference_type`,通常是与容器相关的整数类型 `int` `size_t` 2. 自定义对象的比较 需要重载 `operator==`,以便算法能够比较对象是否相等 3. 性能 是线性查找算法,时间复杂度为 O(n),其中 n 是范围内的元素数量 4. 范围的正确性 确保 first 和 last 指向的范围是有效的,并且 first 不大于 last ### binary-search 用于在*有序序列*中查找是否存在某个值,基于二分查找的思想,时间复杂度为 O(log n) 只返回布尔值,表示是否找到目标值,如果需要找到目标值的位置,可以结合 `std::lower_bound` 或 `std::upper_bound` 使用 ``` template bool binary_search(ForwardIterator first, ForwardIterator last, const T& value); ``` + ForwardIterator:正向迭代器类型,表示要搜索的范围的起始和结束位置。 + first:指向范围的起始位置的迭代器。 + last:指向范围的结束位置的迭代器(不包含)。 + value:要查找的目标值。 + 返回值:如果找到目标值,返回 true;否则返回 false。 __还支持自定义比较函数__ ``` template bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); ``` + Compare:比较函数,用于定义元素之间的大小关系。如果未提供,会使用默认的 < 比较运算符 ## 修改性算法 ### copy 用于将一个范围内的元素复制到另一个范围中,是一个线性算法,时间复杂度为 O(n) ``` template OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); ``` + InputIterator:输入迭代器类型,表示要复制的源范围的起始和结束位置。 + first:指向源范围的起始位置的迭代器。 + last:指向源范围的结束位置的迭代器(不包含)。 + OutputIterator:输出迭代器类型,表示目标范围的起始位置。 + result:指向目标范围的起始位置的迭代器。 + 返回值:返回指向目标范围结束位置的迭代器(即 result + (last - first)) ### replace 用于在指定范围内将所有等于某个特定值的元素替换为另一个值 ``` template 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 void reverse(BidirectionalIterator first, BidirectionalIterator last); ``` + BidirectionalIterator:双向迭代器类型,表示要反转的范围的起始和结束位置。 + first:指向范围的起始位置的迭代器。 + last:指向范围的结束位置的迭代器(不包含) ## 排序算法 ### sort 指定范围内的元素进行排序,要求输入范围的迭代器是随机访问迭代器,是不稳定的排序算法,平均时间复杂度为 O(n log n) ``` template void sort(RandomAccessIterator first, RandomAccessIterator last); ``` + RandomAccessIterator:随机访问迭代器类型,表示要排序的范围的起始和结束位置 + first:指向范围的起始位置的迭代器 + last:指向范围的结束位置的迭代器(不包含) 此外,std::sort 还支持自定义比较函数 ``` template void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); ``` ### stable-sort 是一个稳定排序算法,对指定范围内的元素进行排序,同时保证相等元素的相对顺序不变 ``` template void stable_sort(RandomAccessIterator first, RandomAccessIterator last); template 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 void nth_element(RandomIt first, RandomIt nth, RandomIt last); template 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 T accumulate(InputIterator first, InputIterator last, T init); template T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation op); ``` + InputIterator:输入迭代器类型,表示要操作的范围的起始和结束位置。 + first:指向范围的起始位置的迭代器。 + last:指向范围的结束位置的迭代器(不包含)。 + T:累积结果的类型。 + init:初始值,用于开始累积操作。 + BinaryOperation(可选):二元操作函数,用于定义累积操作。如果未提供,默认使用加法操作 `std::plus` [预定义函数符](./containers.md#) ### inner-product ## 集合算法 ### set-difference ### merge ## 其他算法 ### unique 用于移除序列中相邻的重复元素,并返回一个指向“新序列”结束位置的迭代器。它不会改变原序列的长度,而是将重复元素移动到序列末尾,并返回一个指向“有效部分”结束位置的迭代器。因此,通常需要结合容器的 erase 方法来真正移除重复元素,O(n) ``` template ForwardIterator unique(ForwardIterator first, ForwardIterator last); template ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred); ``` + ForwardIterator:正向迭代器类型,表示要操作的序列的起始和结束位置。 + first:指向序列起始位置的迭代器。 + last:指向序列结束位置的迭代器(不包含)。 + BinaryPredicate(可选):二元谓词函数,用于定义两个元素是否相等。如果未提供,默认使用 operator== ### shuffle 随机打乱指定范围内元素的顺序 ``` template void shuffle(RandomAccessIterator first, RandomAccessIterator last, URNG&& g); ``` + first 和 last:随机访问迭代器,分别指向要打乱范围的起始位置和结束位置(不包含) + URNG:均匀随机数生成器,例如 `std::mt19937` 或 `std::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); ```