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 ...
随机推荐
- 剑指offer--38.左旋转字符串
时间限制:1秒 空间限制:32768K 热度指数:173814 本题知识点: 字符串 题目描述 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果. ...
- JSP的EL和JSTL解析
1. EL 简介EL 全名为Expression Language,所有EL都是以${ 为起始.以} 为结尾的.EL 语法很简单,它最大的特点就是使用上很方便. 接下来介绍EL 主要的语法结构: ${ ...
- 【dlbook】正则化
对学习算法的修改——旨在减少泛化误差而不是训练误差 显著减少方差而不过度增加偏差. [参数范数惩罚] 通常只对权重做惩罚而不对偏置做惩罚,原因是拟合偏置比拟合权重容易很多. 不同层使用不同惩罚的代价很 ...
- 从头搭建一个React应用
node,webpack这些就不一一介绍怎么安装了,默认大家都知道. 一.npm install -g create-react-app 首先全局安装react的脚手架工具 create-react- ...
- EP-N8530S USB WIFI 驱动移植
/*********************************************************************** * EP-N8530S USB WIFI 驱动移植 * ...
- 【ci框架学习】控制器-视图
基础的东西就不写了,网上大把的教程,可以慢慢磨.这里说些要注意的要点. 1.所有控制器都必须间接或者直接继承控制器基类 CI_Controller. 2.文件命名尽量小写,因为ci使用的是pathin ...
- 使用LinkedBlockingQueue来实现生产者消费者的例子
工作中,经常有将文件中的数据导入数据库的表中,或者将数据库表中的记录保存到文件中.为了提高程序的处理速度,可以设置读线程和写线程,这些线程通过消息队列进行数据交互.本例就是使用了LinkedBlock ...
- threejs Object的点击(鼠标)事件(获取点击事件的object)
objects=[]; raycaster = new THREE.Raycaster(); mouse = new THREE.Vector2(); //监听全局点击事件,通过ray检测选中哪一个o ...
- 【转载】分布式之redis复习精讲
注: 本篇文章转自:分布式之redis复习精讲 引言 为什么写这篇文章? 博主的<分布式之消息队列复习精讲>得到了大家的好评,内心诚惶诚恐,想着再出一篇关于复习精讲的文章.但是还是要说明一 ...
- ssm异常;
问题:Invalid bound statement (not found): com.itq.mapper.TbItemMapper.selectByExample 解决:修改pom.xml文件中添 ...