nth_element函数深入
nth_element 是 C++ 标准模板库 (STL) 中的一个非常有用的算法,它的功能是对范围内的元素进行部分排序,使得第 n 小的元素排到指定位置,其前面的元素都小于等于它,后面的元素都大于等于它,但前后的元素不一定是完全排序的。
nth_element 算法基于快速排序,时间复杂度在平均情况下是 O(n),最坏情况是 O(n^2),但通过随机化选取枢轴可以避免最坏情况的频繁发生。
函数原型
1 | template<class RandomIt> |
first: 范围的起始迭代器。nth: 指定要找到的第 n 小元素的迭代器。last: 范围的结束迭代器(不包括last指向的元素)。comp: 可选的自定义比较器,用于自定义排序规则。
nth_element 的核心特点
- 部分排序:
nth_element不会对整个数组进行完全排序,而只会确保第n小的元素排到第n位。 - 前后区间无序:在
nth_element之后,[first, nth)中的元素只会比*nth小,[nth+1, last)中的元素比*nth大,但这些子区间并不会是有序的。
用法示例
1 |
|
输出:
1 | 第5小的元素是:5 |
在这个示例中,nth_element 保证 vec[4] 是第 5 小的元素(因为从 0 开始计数),并且前 4 个元素小于等于 5,后面的元素大于等于 5,但前后部分的元素是无序的。
nth_element 的应用场景
- Top K 问题:你可以用
nth_element来高效找到数组中前 K 大(或前 K 小)元素,而不需要对整个数组排序。 - 中位数查找:用
nth_element可以高效找到无序数组中的中位数,避免排序的 O(n log n) 时间开销。 - 数据过滤:可以用
nth_element来过滤掉过大或过小的元素,只保留前面或后面的一部分。
nth_element 与完整排序的对比
相比 std::sort 或 std::partial_sort,nth_element 只确保第 n 小的元素在正确位置,并且左右部分并不保证是有序的。这使得它在需要部分排序的场景下更加高效。
实现原理
nth_element 实际上是基于快速选择 (Quickselect) 算法的变种。它采用与快速排序类似的分区策略,只不过在每次分区后,它仅处理包含第 n 小元素的那一部分。这使得它比对整个数组进行完全排序更快。
- 选取一个枢轴元素,并将比它小的元素放到左边,大的放到右边。
- 如果
n恰好是枢轴的位置,则排序结束。 - 如果
n小于枢轴的位置,则递归处理左半部分;如果n大于枢轴的位置,则递归处理右半部分。
自定义比较器
可以通过自定义比较器改变 nth_element 的排序规则。例如,按照降序排列:
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 全之の博客!
