STL 算法库 reference
排序相关STL
给出一些实用的排序相关函数。
sort()
通常采用内省排序(Introsort),其混合了快速排序、插入排序、堆排序,根据递归的数据量与层次自动选择,平均时间复杂度 $O(n \log n)$
1 2 |
|
sort
函数附带一个可选参数,用来自定义排序规则:
1 2 3 4 5 |
|
自定义函数的返回值作为判断大小的标准,比如:
1 2 3 4 5 6 7 8 9 |
|
cmp
函数还可以用 Lambda
表达式代替:
1 |
|
事实上 cmp
可以是任何的可调用对象,只要满足:接受两个输入;返回值 bool
;比较关系满足严格弱序。
关于排序规则 cmp
排序规则 cmp
必须满足对比较元素的严格弱序(Strict Weak Ordering),这对 所有涉及 Compare 的函数都有效
如果 cmp
不满足严格弱序(比如 return x <= y
),会出现不可预料的错误
题目举例:P2123 皇后游戏,作为一道贪心排序题,cmp 函数的构造需要考虑到严格弱序的约束,很有趣的题目,调了两天
另外,sort
函数用到了快速排序,所以是不稳定的;可以使用 stable_sort
函数,其通过牺牲空间复杂度确保了排序的稳定性
partial_sort()
相比 sort
函数,partial_sort
函数可以指定将排序进行到部分程度便停止,比如:
1 |
|
此时的排序结果只有 vec[0] ~ vec[k]
是有序的 ,在此之后的序列不保证有序
底层采用堆排序,对从较大的数据量中找到小部分最值结果的搜索很有用,时间复杂度 $O(n \log l)$,$l$ 为待排序部分的长度
该函数有一个变种 partial_sort_copy()
,可以将部分排序的结果存入另一个容器中:
1 2 |
|
partial_sort()
是不稳定的,并且没有稳定版本。
nth_element()
只将第 k + 1
小的元素放在正确的排序位置 vec[k]
,并且这个元素左侧的其他元素都比它小( ≤ ),右侧的其他元素都比它大( ≥ )。时间复杂度 $O(n)$
(类似于快速排序算法中 partition
的实现,但是后者没有“找到第 k 小的元素”这一步,后者的 pivot
没有限制条件)
比如:
1 |
|
令 k = 2
,这样的排序只有 vec[2]
的位置一定是正确的:
1 2 3 |
|
is_sorted()
判断是否有序,返回 true / false
。
1 |
|
is_sorted_until()
查找最长的已排序区间,返回的是不再排序的第一个元素的迭代器。
1 |
|
可以通过 if (it == vec.end())
判断是否完全排序(vec.end()
指向的并不是容器最后一个元素);
可以通过 distance(vec.begin(), it)
获取第一个未排序元素的下标;
(it
可以看作指针, *it
就是迭代器指向元素的值)
partition()
将所有满足谓词 p
的元素放到容器前面,返回一个迭代器,指向第一个不满足筛选规则的元素。
1 |
|
比如(p
通常采用 Lambda 表达式,也可以用独立函数表示):
1 2 3 4 |
|
partition()
具有稳定版本 stable_partition()
可以保证元素的相对顺序
查找相关STL
给出一些实用的查找相关函数。
find()
在一个无需排序的范围内查找第一个等于给定值的元素,返回的是迭代器。
1 |
|
find_if()
在一个无需排序的范围内查找第一个满足给定谓词的元素,返回的是迭代器。
1 |
|
(还有一个 find_if_not()
的变种,查找第一个不满足给定谓词的元素)
binary_search()
在一个已经排序的范围内查找是否包含等于给定值的元素,返回的是 bool
值。
1 |
|
可以采用自定义函数 cmp
决定排序规则,要求原排序范围的排序规则也是 cmp
;
可以通过 if (it == vec.end())
判断是否找到需求的元素。
equal_range()
在一个已经排序的范围内查找所有等于给定值的元素的范围,返回的是 std::pair<it,it>
(包含了两个迭代器的模板类)
1 2 |
|
可以采用自定义函数 cmp
决定排序规则,要求原排序范围的排序规则也是 cmp
;
可以通过 if (it == vec.end())
判断是否找到需求的元素。
lower_bound()
和 upper_bound()
在一个已经排序的范围内查找第一个不小于(lower) / 大于(upper) 给定值的元素,返回的是迭代器。
1 2 |
|
可以采用自定义函数 cmp
决定排序规则,要求原排序范围的排序规则也是 cmp
;
可以通过 if (it == vec.end())
判断是否找到需求的元素。