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()) 判断是否找到需求的元素。