一.源码分析
cpp
_EXPORT_STD template <class _RanIt, class _Pr>
_CONSTEXPR20 void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred) { // order [_First, _Last)
_Adl_verify_range(_First, _Last);
const auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
_Sort_unchecked(_UFirst, _ULast, _ULast - _UFirst, _Pass_fn(_Pred));
}
cpp
template <class _RanIt, class _Pr>
_CONSTEXPR20 void _Sort_unchecked(_RanIt _First, _RanIt _Last, _Iter_diff_t<_RanIt> _Ideal, _Pr _Pred) {
// order [_First, _Last)
for (;;) {
if (_Last - _First <= _ISORT_MAX) { // small
_Insertion_sort_unchecked(_First, _Last, _Pred);
return;
}
if (_Ideal <= 0) { // heap sort if too many divisions
_Make_heap_unchecked(_First, _Last, _Pred);
_Sort_heap_unchecked(_First, _Last, _Pred);
return;
}
// divide and conquer by quicksort
auto _Mid = _Partition_by_median_guess_unchecked(_First, _Last, _Pred);
_Ideal = (_Ideal >> 1) + (_Ideal >> 2); // allow 1.5 log2(N) divisions
if (_Mid.first - _First < _Last - _Mid.second) { // loop on second half
_Sort_unchecked(_First, _Mid.first, _Ideal, _Pred);
_First = _Mid.second;
} else { // loop on first half
_Sort_unchecked(_Mid.second, _Last, _Ideal, _Pred);
_Last = _Mid.first;
}
}
函数逻辑
-
小范围排序 :如果待排序范围小于或等于
_ISORT_MAX (32)
,则直接使用插入排序进行排序。插入排序在小范围内通常比快速排序更快,因为它的常数开销更小。 -
堆排序 :如果
_Ideal
(表示理想的分割次数)小于等于 0,表示递归深度超过了限制,此时使用堆排序来避免快速排序的最坏情况(例如当输入已经排序时,快速排序的时间复杂度为 O(n²))。 -
快速排序 :在快速排序部分,该算法会使用
_Partition_by_median_guess_unchecked
函数来选择枢轴元素,将待排序范围划分成两部分,然后递归地对两部分分别进行排序:调整理想分割次数 :++根据当前分割次数减少_Ideal
的值,以控制递归深度。通过右移操作,_Ideal
会递减,从而限制递归深度。++ -
递归排序 :根据子数组的大小选择先递归处理哪个部分,以减少栈的深度:++如果左半部分小于右半部分,则优先处理左半部分,接着处理右半部分。否则先处理右半部分。++