本系列文章介绍了所有的STL常用的算法。这些算法通常都有不同的功能,例如:排序元素算法{sort()、stable_sort()、nth_element()}、 查询元素算法{find()、find_if()、find_if_not()、find_end()、find_first_of()、adjacent_find()}、 复制元素算法{copy()、strcpy()、strncpy()、memcpy()、copy_n()、copy_if()、copy_backward()}、 删除元素算法{remove()、remove_copy()、remove_if()、remove_copy_if()}、 搬移元素算法{move()、move_backward()}、 归并元素算法{merge()、inplace_merge()}、 交换区间元素算法{swap_ranges()}、区间元素赋值算法{fill()、fill_n()}、 替换区间元素算法{replace()、replace_if()、replace_copy()}、旋转序列元素算法{rotate()、rotate_copy()}、自定义筛选元素算法{partition()、stable_partition()、partition_copy()、partition_point()}、 序列元素去重算法{unique()}、 元素比较算法{permutation()、prev_permutation()、is_permutation()}
本文作者原创,转载请附上文章出处与本文链接。
C++ 标准库 常用算法总结(排序、合并、搜索和分区)目录
1.1 sort()、stable_sort()、nth_element()
1.3 is_sorted()、is_sorted_until()
2.1 find()、find_if()、find_if_not()、find_end()、find_first_of()、adjacent_find()
2.4 lower_bound()、upper_bound()、equel_range()、binary_search()
3.1 copy()、strcpy()、strncpy()、memcpy()、copy_n()、copy_if()、copy_backward()
4.1 remove()、remove_copy()、remove_if()、remove_copy_if()
9.1 replace()、replace_if()、replace_copy()
11.1 partition()、stable_partition()、partition_copy()、partition_point()
13.3 permutation()、prev_permutation()、is_permutation()
13.5 lexicographical_compare()
1 C++ 排序元素算法
1.1 sort()、stable_sort()、nth_element()
sort函数用于C++中,对给定区间所有元素进行排序,默认为升序,也可进行降序排序。sort函数进行排序的时间复杂度为n*log2n,比冒泡之类的排序算法效率要高,sort函数包含在头文件为#include<algorithm>的c++标准库中。
C++ sort()排序函数用法详解(深入了解,一文学会)_c++中sort函数用法_双子座断点的博客-CSDN博客
1.2 partial_sort()
partial_sort()分为partial_sort()和partial_sort_copy()两种函数:
partial_sort()排序函数主要用在非常大的容器筛选最大或者最小值来使用,例如:容器A有100万个元素,需要找出最大或者最小的10个元素,这时候就需要用到partial_sort()和partial_sort_copy()两种函数。
partial_sort() 重新调整容器元素顺序,达到选出最大值或者最小值的目的;partial_sort_copy() 通过复制出最大值或者最小值的方式来达到目的;
C++ partial_sort()排序函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_partial_sort
1.3 is_sorted()、is_sorted_until()
is_sorted() 函数专门用于判断某个序列是否为有序序列。
C++ is_sorted()排序函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客
1.4 all_of any_of none_of
algorithm 头文件中定义了 3 种算法,用来检查在算法应用到序列中的元素上时,什么时候使谓词返回 true。这些算法的前两个参数是定义谓词应用范围的输入迭代器;第三个参数指定了谓词。检查元素是否能让谓词返回 true 似乎很简单,但它却是十分有用的。
例如,可以检查所有学生是否通过了考试,或者检查所有学生是否都参加了课程,或者检查有没有眼睛发绿的 Person 对象,甚至可以检查每个 Dog 对象是否度过了它自己的一天。谓词可以简单,也可以复杂,这取决于你。检查元素属性的三种算法是:
all_of() 算法会返回 true,前提是序列中的所有元素都可以使谓词返回 true。
any_of() 算法会返回 true,前提是序列中的任意一个元素都可以使谓词返回 true。
none_of() 算法会返回 true,前提是序列中没有元素可以使谓词返回 true。
C++ all_of、any_of及none_of排序算法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客
2 C++ 查询元素算法
2.1 find()、find_if()、find_if_not()、find_end()、find_first_of()、adjacent_find()
find函数提供了一种对数组数组、STL容器进行查找的方法。
C++ find()排序函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_c++ find如何寻找第一比他大的位置
2.2 search()
find_end() 函数用于在序列 A 中查找序列 B 最后一次出现的位置。那么,如果想知道序列 B 在序列 A 中第一次出现的位置,该如何实现呢?可以借助 search() 函数。
C++ search()函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_c++ search
2.3 search_n()
和 search() 一样,search_n() 函数也定义在<algorithm>
头文件中,用于在指定区域内查找第一个符合要求的子序列。不同之处在于,前者查找的子序列中可包含多个不同的元素,而后者查找的只能是包含多个相同元素的子序列。
C++ search_n()函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_search_n
2.4 lower_bound()、upper_bound()、equel_range()、binary_search()
find()、find_if()、search() 等。值得一提的是,这些函数的底层实现都采用的是顺序查找(逐个遍历)的方式,在某些场景中的执行效率并不高。例如,当指定区域内的数据处于有序状态时,如果想查找某个目标元素,更推荐使用二分查找的方法(相比顺序查找,二分查找的执行效率更高)。
C++ lower_bound() upper_bound() 函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客
3 C++ 复制元素算法
3.1 copy()、strcpy()、strncpy()、memcpy()、copy_n()、copy_if()、copy_backward()
C++ 算法 copy() 函数用于将容器 [first,last] 的所有元素从结果开始复制到不同的容器中。
本文介绍了copy、strcpy、strncpy、memcpy、copy_n、copy_if、copy_backward等使用方法和代码示例
C++ copy()函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_c++ copy
3.2 reverse()、reverse_copy()
reverse_copy() 算法可以将源序列复制到目的序列中,目的序列中的元素是逆序的。定义源序列的前两个迭代器参数必须是双向迭代器。目的序列由第三个参数指定,它是目的序列的开始迭代器,也是一个输出迭代器。如果序列是重叠的,函数的行为是未定义的。这个算法会返回一个输出迭代器,它指向目的序列最后一个元素的下一个位置。
C++ reverse()函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_c++ reverse
4 C++ 删除元素算法
4.1 remove()、remove_copy()、remove_if()、remove_copy_if()
如果不知道具体的场景,即元素保存在什么样的容器中,是不能从序列中移除元素的。因此,“移除元素的”算法也无法做到这一点,它们只会重写被选择的元素或者忽略复制的元素。移除操作不会改变被“移除”元素的序列的元素个数。
- remove() 可以从它的前两个正向迭代器参数指定的序列中移除和第三个参数相等的对象。基本上每个元素都是通过用它后面的元素覆盖它来实现移除的。它会返回一个指向新的最后一个元素之后的位置的迭代器。
- remove_copy() 可以将前两个正向迭代器参数指定的序列中的元素复制到第三个参数指定的目的序列中,并忽略和第 4 个参数相等的元素。它返回一个指向最后一个被复制到目的序列的元素的后一个位置的迭代器。序列不能是重叠的。
- remove_if() 可以从前两个正向迭代器指定的序列中移除能够使作为第三个参数的谓词返回 true 的元素。
- remove_copy_if() 可以将前两个正向迭代器参数指定的序列中,能够使作为第 4 个参数的谓词返回 true 的元素,复制到第三个参数指定的目的序列中。它返回一个指向最后一个被复制到目的序列的元素的后一个位置的迭代器。序列不能是重叠的。
C++ remove()函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_c++ remove
5 C++ 搬移元素算法
5.1 move()、move_backward()
move() 算法会将它的前两个输入迭代器参数指定的序列移到第三个参数定义的目的序列的开始位置,第三个参数必须是输出迭代器。这个算法返回的迭代器指向最后一个被移动到目的序列的元素的下一个位置。
这是一个移动操作,因此无法保证在进行这个操作之后,输入序列仍然保持不变;源元素仍然会存在,但它们的值可能不再相同了,因此在移动之后,就不应该再使用它们。如果源序列可以被替换或破坏,就可以选择使用 move() 算法。如果不想扰乱源序列,可以使用 copy() 算法。
C++ move()排序函数用法详解(深入了解,一文学会)_c++中move函数用法_双子座断点的博客-CSDN博客
6 C++ 归并元素算法
6.1 merge()、inplace_merge()
我们将 2 个有序序列合并为 1 个有序序列,这时就可以借助 merge() 或者 inplace_merge() 函数实现。
C++ merge()和inplace_merge()函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_inplace_merge
7 C++ 交换区间元素算法
7.1 swap_ranges()
可以用 swap_ranges() 算法来交换两个序列。这个算法需要 3 个正向迭代器作为参数。前两个参数分别是第一个序列的开始和结束迭代器,第三个参数是第二个序列的开始迭代器。显然,这两个序列的长度必须相同。这个算法会返回一个迭代器,它指向第二个序列的最后一个被交换元素的下一个位置。
C++ swap_ranges()排序函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客
7.2 transform()
transform() 可以将函数应用到序列的元素上,并将这个函数返回的值保存到另一个序列中,它返回的迭代器指向输出序列所保存的最后一个元素的下一个位置。
C++ transform(STL transform)函数用法详解
8 C++ 区间元素赋值算法
8.1 fill()、fill_n()
fill函数的作用:将一个区间的元素都赋予val值。
函数参数 :fill(vec.begin(), vec.end(), val); val为将要替换的值。
fill函数的作用是:将一个区间的元素都赋予val值。函数参数:fill(first,last,val);//first为容器的首迭代器,last为容器的末迭代器,val为将要替换的值。
C++ fill和fill_n函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_fill_n
8.2 generate()、generate_n()
算法名称 generate
参数 容器遍历起始位置,容器遍历最后一个位置,特定的动作(函数)
返回值 void
作用 以指定动作运算结果填充特定范围内的元素内容
算法名称 generate_n
参数 容器遍历起始位置,容器遍历的个数,特定的动作(函数)
返回值 返回一个迭代器
作用 以指定动作的运算结果填充n个元素内容
C++ generate和generate_n函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_generate_n
8.3 iota()
iota函数对一个范围数据进行赋值:
#include <iostream> // std::cout
#include <algorithm> // std::move_backward
#include <numeric> // std::iota
#include <vector> // std::vector
using namespace std;
int main()
{
int numbers[10];
std::iota(numbers, numbers + 10, 100);
std::cout << "numbers:";
for (int& i : numbers) std::cout << ' ' << i;
std::cout << '\n';
std::vector<double> data(9);
double initial{ -4 };
std::iota(std::begin(data), std::end(data), initial);
for (int i = 0; i < data.size(); i++) std::cout << ' ' << data[i];
std::cout << '\n';
std::vector<double> dataTwo(9);
double initialTwo{ -2.5 };
std::iota(std::begin(dataTwo), std::end(dataTwo), initialTwo);
for (int i = 0; i < dataTwo.size(); i++) std::cout << ' ' << dataTwo[i];
// Values are -2.5 -1.5 -0.5 0.5 1.5 2.5 3.5 4.5 5.5
return 0;
}
9 C++ 替换区间元素算法
9.1 replace()、replace_if()、replace_copy()
- 会用新的值来替换和给定值相匹配的元素。它的前两个参数是被处理序列的正向迭代器,第 3 个参数是被替换的值,第 4 个参数是新的值。
- 会将使谓词返回 true 的元素替换为新的值。它的第 3 个参数是一个谓词,第 4 个参数是新的值。参数的类型一般是元素类型的 const 引用;const 不是强制性的,但谓词不应该改变元素。
- 算法和 replace() 做的事是一样的,但它的结果会被保存到另一个序列中,而不会改变原始序列。它的前两个参数是输入序列的正向迭代器,第 3 个参数是输入序列的开始迭代器,最后两个参数分别是要被替换的值和替换值。
C++ replace,replace_if和replace_copy函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_replace if &
10 C++ 旋转序列元素算法
10.1 rotate()、rotate_copy()
为了理解如何旋转序列,可以将序列中的元素想象成手镯上的珠子。rotate() 操作会导致一个新元素成为开始迭代器所指向的第一个元素。在旋转之后,最后一个元素会在新的第一个元素之前。
rotate() 的第一个参数是这个序列的开始迭代器;第二个参数是指向新的第一个元素的迭代器,它必定在序列之内。第三个参数是这个序列的结束迭代器。图 1 中的示例说明在容器 ns 上的旋转操作使值为 4 的元素成为新的第一个元素,最后一个元素的值为 3。元素的圆形序列会被维持,因此可以有效地旋转元素环,直到新的第一个元素成为序列的开始。这个算法会返回一个迭代器,它指向原始的第一个元素所在的新位置。
C++ rotate()排序函数用法详解(深入了解,一文学会)_c++rotate函数_双子座断点的博客-CSDN博客
11 C++ 自定义筛选元素算法
11.1 partition()、stable_partition()、partition_copy()、partition_point()
partition 可直译为“分组”,partition() 函数可根据用户自定义的筛选规则,重新排列指定区域内存储的数据,使其分为 2 组,第一组为符合筛选条件的数据,另一组为不符合筛选条件的数据。
C++ partition()和stable_partition()函数用法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_c++ partition
12 C++ 序列元素去重算法
12.1 unique()
unique() 算法可以在序列中原地移除重复的元素,这就要求被处理的序列必须是正向迭代器所指定的。在移除重复元素后,它会返回一个正向迭代器作为新序列的结束迭代器。可以提供一个函数对象作为可选的第三个参数,这个参数会定义一个用来代替 ==
比较元素的方法。
C++ unique算法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客
13 C++ 元素比较算法
13.1 equal()
比较常见比较字符串很简单自行百度
13.2 mismatch()
可以用和比较字符串类似的方式来比较序列。如果两个序列的长度相同,并且对应元素都相等,equal() 算法会返回 true。有 4 个版本的 equal() 算法,其中两个用 == 运算符来比较元素,另外两个用我们提供的作为参数的函数对象来比较元素,所有指定序列的迭代器都必须至少是输入迭代器。
用 == 运算符来比较两个序列的第一个版本期望 3 个输入迭代器参数,前两个参数是第一个序列的开始和结束迭代器,第三个参数是第二个序列的开始迭代器。如果第二个序列中包含的元素少于第一个序列,结果是未定义的。用 == 运算符的第二个版本期望 4 个参数:第一个序列的开始和结束迭代器,第二个序列的开始和结束迭代器,如果两个序列的长度不同,那么结果总是为 false。
C++ mismatch(STL mismatch)算法详解_双子座断点的博客-CSDN博客
13.3 permutation()、prev_permutation()、is_permutation()
- 是按照字典升序的方式生成的排列,该算法输入一组数组,打印出所有全排列。
- 是按照字典升序的方式生成的排列
C++ permutation排列算法详解(深入了解,一文学会)_双子座断点的博客-CSDN博客_c++ permutation
13.4 next_permutation()
排列就是一次对对象序列或值序列的重新排列。例如,“ABC”中字符可能的排列是:
"ABC", "ACB", "BAC", "BCA", "CAB", "CBA"
三个不同的字符有 6 种排列,这个数字是从 3*2*1 得到的。一般来说,n 个不同的字 符有 n! 种排列,n! 是 nx(n_1)x(n-2)...x2x1。很容易明白为什么要这样算。有 n 个对象 时,在序列的第一个位置就有 n 种可能的选择。对于第一个对象的每一种选择,序列的第 二个位置还剩下 n-1 种选择,因此前两个有 nx((n-1) 种可能选择。在选择了前两个之后, 第三个位置还剩下 n-2 种选择,因此前三个有 nx(n-1)x(n-2) 种可能选择,以此类推。序列的末尾是 Hobson 选择,因为只剩下 1 种选择。
对于包含相同元素的序列来说,只要一个序列中的元素顺序不同,就是一种排列。next_permutation() 会生成一个序列的重排列,它是所有可能的字典序中的下一个排列,默认使用 < 运算符来做这些事情。它的参数为定义序列的迭代器和一个返回布尔值的函数,这个函数在下一个排列大于上一个排列时返回 true,如果上一个排列是序列中最大的,它返回 false,所以会生成字典序最小的排列。
C++ next_permutation(STL next_permutation)算法详解
13.5 lexicographical_compare()
两个字符串的字母排序是通过从第一个字符开始比较对应字符得到的。第一对不同的对应字符决定了哪个字符串排在首位。字符串的顺序就是不同字符的顺序。如果字符串的长度相同,而且所有的字符都相等,那么这些字符串就相等。如果字符串的长度不同,短字符串的字符序列和长字符串的初始序列是相同的,那么短字符串小于长字符串。因此 “age” 在“beauty” 之前,“a lull” 在 “a storm” 之前。显然,“the chicken” 而不是 “the egg” 会排在首位。
对于任何类型的对象序列来说,字典序都是字母排序思想的泛化。从两个序列的第一个元素开始依次比较对应的元素,前两个对象的不同会决定序列的顺序。显然,序列中的对象必须是可比较的。
lexicographical_compare()算法可以比较由开始和结束迭代器定义的两个序列。它的前两个参数定义了第一个序列,第 3 和第 4 个参数分别是第二个序列的开始和结束迭代器。默认用 < 运算符来比较元素,但在需要时,也可以提供一个实现小于比较的函数对象作为可选的第 5 个参数。如果第一个序列的字典序小于第二个,这个算法会返回 true,否则返回 false。所以,返回 false 表明第一个序列大于或等于第二个序列。
序列是逐个元素比较的。第一对不同的对应元素决定了序列的顺序。如果序列的长度不同,而且短序列和长序列的初始元素序列匹配,那么短序列小于长序列。长度相同而且对应元素都相等的两个序列是相等的。空序列总是小于非空序列。
C++ lexicographical_compare()字符串排序算法详解_双子座断点的博客-CSDN博客