C++ 之 标准模板库的七大算法

标准模板库的算法

STL中的算法大致可以分为以下七类:

  • 不变序列算法
  • 变值算法
  • 删除算法
  • 变序算法
  • 排序算法
  • 有序区间算法
  • 数值算法

特性 :

  • 算法就是一个个函数模板,大多数在<algorithm>中定义
  • STL中提供能在各种容器中通用的算法,比如查找,排序等
  • 算法通过迭代器来操纵容器中的元素。许多算法可以对容器中的一个局部区间进行操作,因此需要两个参数,一个是起始元素的选代器,一个是终止元素的后面一个元素的迭代器。比如,排序和查找
  • 有的算法返回一个迭代器。比如find()算法,在容器中查找一个元素,并返回一个指向该元素的迭代器
  • 算法可以处理容器,也可以处理普通数组

不变序列算法

  • 该类算法不会修改算法所作用的容器或对象
  • 适用于顺序容器和关联容器
  • 时间复杂度都是O(n)
算法 作用
min 求两个对象中较小的(可自定义比较器)
max 求两个对象中较大的(可自定义比较器)
min_element 求区间中的最小值(可自定义比较器)
max_element 求区间中的最大值(可自定义比较器)
for_each 对区间中的每个元素都做某种操作
count 计算区间中等于某值的元素个数
count_if 计算区间中符合某种条件的元素个数
find 在区间中查找等于某值的元素
find_if 在区间中查找符合某条件的元素
find_end 在区间中查找另一个区间最后一次出现的位置(可自定义比较器)
find_first_of 在区间中查找第一个出现在另一个区间中的元素(可自定义比较器)
adjacent_find 在区间中寻找第一次出现连续两个相等元素 的位置(可自定义比较器)
search 在区间中查找另一个区间第一次出现的位置(可自定义比较器)
search_n 在区间中查找第一次出现等于某值的连续n个元素(可自定义比较器)
equal 判断两区间是否相等(可自定义比较器)
mismatch 逐个比较两个区间的元素,返回第一次发生不相等的两个元素的位置(可自定义比较器)
lexicographical_compare 按字典序比较两个区间的大小(可自定义比较器)

算法示例 : find()

template<class Inlt,class T>
Inlt find(Inlt first,Inlt last,const T& val);
  • first和last 这两个参数都是容器的迭代器,它们给出了容器中的查找区间起点和终点[first,last)。区间的起点是位于查找范围之中的,而终点不是。find在[first,last)查找等于val的元素
  • 用==运算符判断相等
  • 函数返回值是一个迭代器。如果找到,则该选代器指向被找到的元素。
  • 如果找不到,则该迭代器等于last

Example:

p=find(v.begin),v.end(),3);
if(!p=v.end())
    cout<<*p<<endl; 

STL中"大""小"的概念

  • 关联容器内部的元素是从小到大排序的
  • 有些算法要求其操作的区间是从小到大排序的,称为"有序区间算法"
    例:binary_search 二分法/折半查找
  • 有些算法会对区间进行从小到大排序,称为"排序算法"
    例:sort
  • 还有一些其他算法会用到"大","小"的概念使用STL时,在缺省的情况下,以下三个说法等价:
    1. x 比 y 小
    2. 表达式"x<y"为真
    3. y 比 x 大

变值算法

  • 此类算法会修改源区间或目标区间元素的值
  • 值被修改的那个区间,不可以是属于关联容器的
算法 作用
for_each 对区间中的每个元素都做某种操作
copy 复制一个区间到别处
copy_backward 复制一个区间到别处,但目标区前是从后往前被修改的
transform 将一个区间的元素变形后拷贝到另一个区间
swap_ranges 交换两个区间内容
fill 用某个值填充区间
fill_n 用某个值替换区间中的n个元素
generate 用某个操作的结果填充区间
generate_n 用某个操作的结果替换区间中的n个元素
replace 将区间中的某个值替换为另一个值
replace_if 将区间中符合某种条件的值替换成另一个值

删除算法

  • 删除一个容器里的某些元素
  • 删除--不会使容器里的元素减少
    • 将所有应该被删除的元素看做空位子
    • 用留下的元素从后往前移,依次去填空位子
    • 元素往前移后,它原来的位置也就算是空位子
    • 也应由后面的留下的元素来填上
    • 最后,没有被填上的空位子,维持其原来的值不变删除算法不应作用于关联容器
  • 删除算法不应作用于关联容器
  • 算法复杂度都是O(n)的
算法 作用
remove 删除区间中等于某个值的元素
remove_if 删除区间中满足某种条件的元素
remove_copy 拷贝区间到另一个区间,等于某个值的元素不拷贝
remove_copy_if 拷贝区间到另一个区间,符合某种条件的元素不拷贝
unique 删除区间中连续相等的元素,只留下一个(可自定义比较器)
unique_copy 拷贝区间到另一个区间.连续相等的元素,只拷贝第一个到目标区间(可自定义比较器)

变序算法

  • 变序算法改变容器中元素的顺序
  • 但是不改变元素的值
  • 变序算法不适用于关联容器
  • 算法复杂度都是O(n)的
算法 作用
reverse 颠倒区间的前后次序
reverse_Copy 把一个区间颠倒后的结果拷贝到另一个区间,源区间不变
rotate 将区间进行循环左移
rotate_copy 将区间以首尾相接的形式进行旋转后的结果拷贝到另一个区间,源区间不变
next_permutation 将区间改为下一个排列(可自定义比较器)
prev_permutation 将区间改为上一个排列(可自定义比较器)
random_shuffle 随机打乱区间内元素的顺序
partition 把区间内满足某个条件的元素移到前面,不满足该条件的移到后面

排序算法

  • 比前面的变序算法复杂度更高,一般是O(nlog(n))
  • 排序算法需要随机访问迭代器的支持不适用于关联容器和list
算法 作用
sort 将区间从小到大排序(可自定义比较器)将区间从小到大排序
stable_sort 并保持相等元素间的相对次序(可自定义比较器)
partial_sort 对区间部分排序,直到最小的n个元素就位(可自定义比较器)
partial_sort_copy 将区间前n个元素的排序结果拷贝到别处,源区间不变(可自定义比较器)
nth_element 对区间部分排序,使得第n小的元素(n从0开始算)就位,而且比它小的都在它前面,比它大的都在它后面(可自定义比较器)

排序算法 复杂度分析

sort

  • 实际上是快速排序,时间复杂度O(n*log(n))
  • 平均性能最优
  • 但是最坏的情况下,性能可能非常差,如果要保证"最坏情况下"的性能,那么可以使用stable_sort

stable_sort

  • 实际上是归并排序,特点是能保持相等元素之间的先后次序
  • 在有足够存储空间的情况下,复杂度为nlog(n),否则复杂度为nlog(n)*log(n)
  • stable_sort用法和sort相同.
  • 排序算法要求随机存取迭代器的支持,所以ist不能使用

有序区间算法

  • 要求所操作的区间是已经从小到大排好序的
  • 需要随机访问迭代器的支持
  • 有序区间算法不能用于关联容器和list
算法 作用
binary_search 判断区间中是否包含某个元素 O(log(n))
includes 判断是否一个区间中的每个元素,都在另一个区间中
lower_bound 查找最后一个不小于某值的元素的位置
upper_bound 查找第一个大于某值的元素的位置
equal_range 同时获取lower_bound和upper_bound
merge 合并两个有序区间到第三个区间人
set_union 将两个有序区间的并拷贝到第三个区间
set_intersection 将两个有序区间的交拷贝到第三个区间
set difference 将两个有序区间的差拷贝到第三个区间
set_symmetric_difference 将两个有序区间的对称差拷贝到第三个区间
inplace_merge 将两个连续的有序区间原地合并为一个有序区间
posted @ 2021-04-28 22:14  FlameAlpha  阅读(226)  评论(0编辑  收藏  举报