STL sort
STL的sort()算法,数据量大时采用Quick Sort,分段递归排序,一旦分段后的数据量小于某个门槛,为避免Quick Sort的递归调用带来过大的额外负荷,就改用Insertion Sort。如果递归层次过深,还会改用Heap Sort。本文先分别介绍这个三个Sort,再整合分析STL sort算法(以上三种算法的综合) -- Introspective Sorting(内省式排序)。
一、Insertion Sort
Insertion Sort
// 默认以渐增方式排序
template <class RandomAccessIterator>
void __insertion_sort(RandomAccessIterator first,
RandomAccessIterator last)
{
if (first == last) return;
// --- insertion sort 外循环 ---
for (RandomAccessIterator i = first + 1; i != last; ++i)
__linear_insert(first, i, value_type(first));
// 以上,[first,i) 形成一个子区间
}
template <class RandomAccessIterator, class T>
inline void __linear_insert(RandomAccessIterator first,
RandomAccessIterator last, T*)
{
T value = *last; // 记录尾元素
if (value < *first){ // 尾比头还小 (注意,头端必为最小元素)
copy_backward(first, last, last + 1); // 将整个区间向右移一个位置
*first = value; // 令头元素等于原先的尾元素值
}
else // 尾不小于头
__unguarded_linear_insert(last, value);
}
template <class RandomAccessIterator, class T>
void __unguarded_linear_insert(RandomAccessIterator last, T value)
{
RandomAccessIterator next = last;
--next;
// --- insertion sort 内循环 ---
// 注意,一旦不再出现逆转对(inversion),循环就可以结束了
while (value < *next){ // 逆转对(inversion)存在
*last = *next; // 调整
last = next; // 调整迭代器
--next; // 左移一个位置
}
*last = value; // value 的正确落脚处
}
二、Quick Sort
Quick Sort
// 返回 a,b,c之居中者
template <class T>
inline const T& __median(const T& a, const T& b, const T& c)
{
if (a < b)
if (b < c) // a < b < c
return b;
else if (a < c) // a < b, b >= c, a < c --> a < b <= c
return c;
else // a < b, b >= c, a >= c --> c <= a < b
return a;
else if (a < c) // c > a >= b
return a;
else if (b < c) // a >= b, a >= c, b < c --> b < c <= a
return c;
else // a >= b, a >= c, b >= c --> c<= b <= a
return b;
}
Partitioning(分割)
Partitioning
template <class RandomAccessIterator, class T>
RandomAccessIterator __unguarded_partition(
RandomAccessIterator first,
RandomAccessIterator last,
T pivot)
{
while(true){
while (*first < pivot) ++first; // first 找到 >= pivot的元素就停
--last;
while (pivot < *last) --last; // last 找到 <=pivot
if (!(first < last)) return first; // 交错,结束循环
// else
iter_swap(first,last); // 大小值交换
++first; // 调整
}
}
三、Heap Sort
Heap Sort
// paitial_sort的任务是找出middle - first个最小元素。
template <class RandomAccessIterator>
inline void partial_sort(RandomAccessIterator first,
RandomAccessIterator middle,
RandomAccessIterator last)
{
__partial_sort(first, middle, last, value_type(first));
}
template <class RandomAccessIterator,class T>
inline void __partial_sort(RandomAccessIterator first,
RandomAccessIterator middle,
RandomAccessIterator last, T*)
{
make_heap(first, middle); // 默认是max-heap,即root是最大的
for (RandomAccessIterator i = middle; i < last; ++i)
if (*i < *first)
__pop_heap(first, middle, i, T(*i), distance_type(first));
sort_heap(first,middle);
}
四、IntroSort
Intro Sort
template <class RandomAccessIterator>
inline void sort(RandomAccessIterator first,
RandomAccessIterator last)
{
if (first != last){
__introsort_loop(first, last, value_type(first), __lg(last-first)*2);
__final_insertion_sort(first,last);
}
}
// __lg()用来控制分割恶化的情况
// 找出2^k <= n 的最大值,例:n=7得k=2; n=20得k=4
template<class Size>
inline Size __lg(Size n)
{
Size k;
for (k = 0; n > 1; n >>= 1)
++k;
return k;
}
// 当元素个数为40时,__introsort_loop的最后一个参数
// 即__lg(last-first)*2是5*2,意思是最多允许分割10层。
const int __stl_threshold = 16;
template <class RandomAccessIterator, class T, class Size>
void __introsort_loop(RandomAccessIterator first,
RandomAccessIterator last, T*,
Size depth_limit)
{
while (last - first > __stl_threshold){ // > 16
if (depth_limit == 0){ // 至此,分割恶化
partial_sort(first, last, last); // 改用 heapsort
return;
}
--depth_limit;
// 以下是 median-of-3 partition,选择一个够好的枢轴并决定分割点
// 分割点将落在迭代器cut身上
RandomAccessIterator cut = __unguarded_partition
(first, last, T(__median(*first,
*(first + (last - first)/2),
*(last - 1))));
// 对右半段递归进行sort
__introsort_loop(cut,last,value_type(first), depth_limit);
last = cut;
// 现在回到while循环中,准备对左半段递归进行sort
// 这种写法可读性较差,效率也并没有比较好
}
}
template <class RandomAccessIterator>
void __final_insertion_sort(RandomAccessIterator first,
RandomAccessIterator last)
{
if (last - first > __stl_threshold){
// > 16
// 一、[first,first+16)进行插入排序
// 二、调用__unguarded_insertion_sort,实质是直接进入插入排序内循环,
// *参见Insertion sort 源码
__insertion_sort(first,first + __stl_threshold);
__unguarded_insertion_sort(first + __stl_threshold, last);
}
else
__insertion_sort(first, last);
} template <class RandomAccessIterator>
inline void __unguarded_insertion_sort(RandomAccessIterator first,
RandomAccessIterator last)
{
__unguarded_insertion_sort_aux(first, last, value_type(first));
} template <class RandomAccessIterator, class T> void __unguarded_insertion_sort_aux(RandomAccessIterator first,
RandomAccessIterator last,
T*)
{
for (RandomAccessIterator i = first; i != last; ++i)
__unguarded_linear_insert(i, T(*i));
}
if (last - first > __stl_threshold){ // > 16
...
...
__introsort_loop(cut,last,value_type(first), depth_limit);
__introsort_loop(first,cut,value_type(first), depth_limit);

STL sort的更多相关文章
- STL sort 函数实现详解
作者:fengcc 原创作品 转载请注明出处 前几天阿里电话一面,被问到STL中sort函数的实现.以前没有仔细探究过,听人说是快速排序,于是回答说用快速排序实现的,但听电话另一端面试官的声音,感觉不 ...
- STL sort()函数
C++之所以得到这么多人的喜欢,是因为它既具有面向对象的概念,又保持了C语言高效的特点.STL 排序算法同样需要保持高效.因此,对于不同的需求,STL提供的不同的函数,不同的函数,实现的算法又不尽相同 ...
- STL::sort函数实现
声明:本文参考链接:STL::sort实现. 排序是面试中经常被问及的算法基础知识点,虽然实际应用中不会直接使用,但是理解这些简单的算法知识对于更复杂更实用的算法有一定的帮助,毕竟面试总不能问的太过深 ...
- STL sort 函数实现详解 ZZ
前几天阿里电话一面,被问到STL中sort函数的实现.以前没有仔细探究过,听人说是快速排序,于是回答说用快速排序实现的,但听电话另一端面试官的声音,感觉不对劲,知道自己回答错了.这几天特意看了一下,在 ...
- c++ stl sort example
c++ stl sort函数使用举例: #include <iostream> #include<vector> #include<algorithm> #incl ...
- c++ STL sort struct comp
详细解说 STL 排序(Sort) http://www.cppblog.com/mzty/archive/2005/12/15/1770.html 详细解说 STL 排序(Sort) 作者Winte ...
- 分享stl sort函数坑点导致coredump问题
在<Effective STL> 的条款21中就有讨论:永远让比较函数对相同元素返回false! 也就是说在实现stl sort函数自定义比较器时,一定要满足这种严格弱序化的问题.
- STL sort源码剖析
转载自:http://www.cnblogs.com/imAkaka/articles/2407877.html STL的sort()算法,数据量大时采用Quick Sort,分段递归排序,一旦分段后 ...
- STL——sort函数简介
参考:http://blog.csdn.net/s030501408/article/details/5329477 0)与C标准库qsort的比较:http://bbs.csdn.net/topic ...
随机推荐
- PostgreSQL数据库资料(转)
PostgreSQL数据库资料 转自:http://blog.csdn.net/postgrechina/article/details/49132791 推荐书籍: 概念书籍: <Postgr ...
- Visual studio 生成后事件说明
在“配置属性->生成事件->生成后事件”属性页中的“命令行”编辑框中输入如下命令: copy "$(ProjectDir)$(IntDir)\$(ProjectName).t ...
- CSS同时使用背景图片和背景颜色
background:url(../images/bg.jpg) #F3EFE5 no-repeat ;
- windows主机与virtualbox虚拟机下的Linux共享网络
环境: 主机:windows7 虚拟机:virtualbox 4.2 虚拟系统:CentOS6.2 需求: 1.虚拟机linux可以共享主机网络上互联网 2.主机.虚拟机互通讯,组成一个虚拟的局域网, ...
- HDU - 1142:A Walk Through the Forest (拓扑排序)
Jimmy experiences a lot of stress at work these days, especially since his accident made working dif ...
- ssm+PageHelper实现分页查询
通过搭建ssm框架,然后通过mybatis的分页插件pagehelp进行分页查询.源码:https://gitee.com/smfx1314/pagehelper 看一下项目结构: 首先创建一个mav ...
- BZOJ2243 SDOI2011 染色 【树链剖分】
BZOJ2243 SDOI2011 染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色 ...
- 常用输入法快速输入自定义格式的时间和日期(搜狗/QQ/微软拼音)
几个主流的输入法输入 rq 或者 sj 都可以得到预定义格式的日期或者时间.然而他们都是预定义的格式:当我们需要一些其他格式的时候该怎么做呢? 本文将介绍几个常用输入法自定义时间和日期格式的方法. 主 ...
- JavaWeb向浏览器返回一个音频流
浏览器直接播放音频文件,1是直接访问一个html的音频文件,,2 是返回一个Java音频流给浏览器解析. 下面实现一个java的wav文件音频流,可以直接播放音频文件 package org.lib. ...
- maven创建多模块项目
在eclipse下构建maven项目,该项目由多个子模块组成. 1.创建一个父项目 NEW -->project-->maven-->maven Project,点击下一步,进入ne ...