c++ STLSGI STL版本sort函数的实现
Posted 傅耳耳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ STLSGI STL版本sort函数的实现相关的知识,希望对你有一定的参考价值。
0、博客来由
刷单链表排序题时,使用自己写的quick_sort函数会运行超时,但调用STL的sort函数则通过,于是想一探究竟,STL的sort函数是如何实现的
1、STL sort函数简介
2、插入排序 Insertion Sort
2.3 代码
template <typename RandomAccessIterator, typename T>
inline void __linear_insert(RandomAccessIterator first, RandomAccessIterator last, T*)
//将last插入到[first,last-1]中
T value = *last;
if(value < *first)
//比第一个元素还要小
copy_backward(first, last, last + 1);
//整个区间向后移动一个位置
*first = value;
else
__unguarded_linear_insert(last, value);
template <typename RandomAccessIterator, typename T>
void __unguarded_linear_insert(RandomAccessIterator last, T value)
//value插入到last之前的有序序列中
RandomAccessIterator next = last;
--next;//从last-1开始比较
while(value < *next)
//将该值移动到后面
//last = next + 1;
*last = *next;
last = next;
--next;
//跳出位置的last即为value的位置
*last = value;
【代码图解】
3、快速排序 Quick Sort
【Median-of-three三点中值代码】
template <typename T>
inline const T& __median(const T& a, const T& b, const T& c)
if(a < b)
if(b < c)
return b;//a < b < c
else if(a < c)
return c;//a < c < b
else
return a;//c < a < b
else if(a < c)
return a;//b <= a < c
else if(b < c)
return c;//b < c <= a
else
return b;//c <= b <= a
template <typename RandomAccessIterator, typename T>
RandomAccessIterator __unguarded_partition(RandomAccessIterator first, RandomAccessIterator last, T pivot)
//pivot为基准
//对[first,last)进行分割
while(true)
while(*first < pivot) ++ first;
--last;
while(pivot < *last) -- last;
if(!(first < last)) return first;//交错,结束循环
iter_swap(first, last);//两者交换
++first;//调整
4、SGI STL版本的sort实现
4.1 内省式排序 IntroSort
4.2 sort算法实现
4.2.1 sort函数(母函数)
template <typename RandomAccessIterator>
inline void sort(RandomAccessIterator first, RandomAccessIterator last)
if(first != last)
__introsort_loop(first, last, value_type(first), __lg(last-first)*2);
//__lg()用来控制分割恶化的情况
__final_insertion_sort(first, last);
//_lg()函数实现:
//快排平均情况下分割次数为logn,递归次数logn * 2(每次递归两部分,一共分割logn次)
//__lg()求logn,即n除以几次2变为1
template <typename Size>
inline Size __lg(Size n)
Size k;
for(k = 0; n > 1; n >>= 1) ++k;
return k;
4.2.2 __introsort_loop()函数
__stl_threshold为全局常数
const int __stl_threshold = 16;
//introsort_loop函数是对快排的改进
template <typename RandomAccessIterator, typename T, typename Size>
void __introsort_loop(RandomAccessIterator first, RandomAccessIterator last, T*, Size depth_limit)
//__stl_threshold时全局常数
while(last - first > __stl_threshold)
//序列大小 > 阈值
if(depth_limit == 0)
//递归层数超出设置
partial_sort(first, last, last);//改用堆排序
return ;
--depth_limit;
//使用三点中值快速排序
//找三点中值cut
RandomAccessIterator cut = __unguarded_partition(first, last, T(__median(*first, *(first+(last-first)/2), *(last-1))));
//对右半段递归
__introsort_loop(cut, last, value_type(first), depth_limit);
last = cut;
//回到while循坏,开始左半段的递归
4.2.3 插入排序的实现部分
template <typename RandomAccessIterator>
void __final_insertion_sort(RandomAccessIterator first, RandomAccessIterator last)
if(last - first > __stl_threshold)
// > 16
__insertion_sort(first, first + __stl_threshold);
__unguarded_insertion_sort(first + __stl_threshold, last);
//超过16的子段分割为 16 + 剩余
else
__insertion_sort(first, last);
template <typename RandomAccessIterator>
inline void __unguarded_insertion_sort(RandomAccessIterator first, RandomAccessIterator last)
__unguarded_insertion_sort_aux(first, last, value_type(first));
template <typename RandomAccessIterator, typename T>
void __unguarded_insertion_sort_aux(RandomAccessIterator first, RandomAccessIterator last, T*)
//将每个元素逐个从末尾开始插入
for(RandomAccessIterator i = first; i != last; ++ i)
__unguarded_linear_insert(i, T(*i));
//插入单个元素
template <typename RandomAccessIterator, typename T>
void __unguarded_linear_insert(RandomAccessIterator last, T value)
//value插入到last之前的有序序列中
RandomAccessIterator next = last;
--next;//从last-1开始比较
while(value < *next)
//将该值移动到后面
//last = next + 1;
*last = *next;
last = next;
--next;
//跳出位置的last即为value的位置
*last = value;
参考:《STL源码剖析》by 侯捷
5、总结
- 必须是具有随机存取迭代器的容器才可以使用sort排序
- 大数据量采用三点中值快排,小数据量采用插入快排
- 快排分割恶化(递归层数过多)时,采用堆排序
个人认为,sort算法就是一种组合创新,将多种策略的优点融合到一起,取长补短yyds
以上是关于c++ STLSGI STL版本sort函数的实现的主要内容,如果未能解决你的问题,请参考以下文章
为啥用于 stl 函数的 lambda 函数,如 C++ 中的 sort() 、 max_element() 函数需要两个参数作为输入?