STL Sort Algorithm

这个星期看了侯捷先生《STL 源码剖析》算法部分,基本看完了,其中算法比较多,我就重点下Sort在SGI STL中的实现。

1. sort

函数的实现是这样的:

template <class RandomAccessIterator>
inline void sort(RandomIAccessIterator first , RandomAccessIterator last>
{
	if ( first != last) {
		__introsort_loop(fisrt,last, value_type(first), __lg( last - first ) * 2 );
		__final_insertion_sort(first , last);
	}
}

sort针对的是RandomAccessIterator(而像List容器是不能用这个sort,我在List的记录中详细的说明了List自定义的sort算法(QuickSort)),先调用函数__introsort_loop对其排序至大致有序,然后调用__final_insertion_sort函数实现完全排序;

1.1. __introsort_loop

首先对其进行QuickSort,如果分割行为有恶化为二次行为的倾向的时候(QuickSort最差的情况下时间复杂度是O(N^2)),那么这时候转而使用HeapSort,将时间复杂度维持在O(NlogN);

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 ) {
		if (depth_limit == 0) {
			partial_sort (first , last ,last);
			return ;
		}
		--depth_limit;
		RandomIAccessIterator cut = __unguarded_partition ( first , last , T(__median(*first , * (first + (last - first)/2))), *last);
		__introsort_loop(cut , last , value_type(first) , depth_limit);
		last = cut;
	}
}

选择first,(first + (last - first) / 2),last - 1中一个够好的作为分割点,然后调用函数__unguarded_partition进行一次排序,使得比分割点值pivot小的在左边,大的在右边,然后递归调用__introsort_loop;

template <class RandomAccessIterator , class T>
RandomAccessIterator __unguarded_partition ( RandomAccessIterator first , RandomAccessIterator last , T pivot)
{
	while (true) {
		while ( *first < pivot ) ++first;

		--last;
		while ( *last  > pivot ) --last;

		if ( !(first < last) ) // only for random access iterator
			return first;

		iter_swap (first , last);
		++first;
	}
}

在出现分割恶化的情况下,调用函数partial_sort,该函数主要是HeapSort,关于堆排序我在下面说继续说明其实现;

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);
	for (RandomAccessIterator i = middle ; i < last ; ++ i)
		if ( *i < *first )
			__pop_heap(first , middle , i ,T(*i) , distance_type(first));
	sort_heap(first , middle);
}

1.2.  __final_insertion_sort

Introspective Sorting之后,使得数列大致有序,然后使用插入排序,这样,会用更优的时间复杂度,插入排序的原理和实现比较简单,这里就不多说了;

template <class RandomAccessIterator>
void __final_insertion_sort(RandomAccessIterator first , RandomAccessIterator last)
{
	if (last - first > __stl_threshold) {
		__insertion_sort (first , first + __stl_threshold);
		__unguarded_insertion_sort ( first + __stl_threshold , last);
	}
	else {
		__insertion_sort(fisrt , 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>
inline void __unguarded_insertion_sort_aux(RandomAccessIterator first , RandomAccessIterator last , T*)
{
	for (RandomAccessIterator i = first ; i != last ; ++i)
		__unguarded_linear_insert (i ,T(*i));
}

template <class RandomAccessIterator>
void __insertion_sort(RandomAccessIterator first ,ge RandomAccessIterator last)
{
	if ( first == last) return;
	for (RandomAccessIterator i = first + 1 ; i != last ; ++i) {
		__linear_insert (first , i ,value_type(first));
	}
}

template <class RandomAccessIterator>
void __linear_insert(RandomAccessIterator first , RandomAccessIterator last , T*)
{
	T value = *last;
	if (value < *first) {
		copy_backward (first , last , last + 1);
		*first = value;
	}
	else
		__unguarded_insertion_sort(last , value);
}

template <class RandomAccessIterator , class T>
void __unguarded_insertion_sort(RandomAccessIterator last , T value)
{
	RandomAccessIterator next = last;
	--next;
	while (value < *next) {
		*last = *next;
		last = next;
		--next;
	}
	*last = value;
}

2. HeapSort

Binary Heap是一种complete binary tree,根据元素排队规则分为max-heap和min-heap,max-heap是最大值在根节点,因为Binary Heap是一种完全二叉树,就可以用数组来表述,

template <class RandomAccessIterator>
inline void make_heap(RandomAccessIterator first , RandomAccessIterator last)
{
	__make_heap(first , last ,value_type(first) , distance_type(first));
}

template <class RandomAccessIterator , class T , class Distance>
void __make_heap(RandomIAccessIterator first , RandomAccessIterator last , T* , Distance *)
{
	if (last - first < 2)
		return;
	Distance len = last - first;
	Distance parent = (len - 2) / 2;
	while (true) {
		__adjust_heap(first , parent , len , T(*(first + parent)));
		if (parent == 0)
			return ;
		parent--;
	}
}

template <class RandomAccessIterator , class Distance , class T>
void __adjust_heap(RandomAccessIterator first , Distance holeIndex , Distance len , T value)
{
	Distance topIndex = holeIndex;
	Distance secondChild = 2 * holeIndex + 2;
	while (secondChild < len) {
		if (*(first + secondChild) < *(first + secondChild - 1))
			--secondChild;
		*(first + holeIndex) = *(first + secondChild);
		holeIndex = secondChild;
		secondChild = 2 * (secondChild + 1);
	}
	if (secondChild == len) {
		*(first + holeIndex) = *(first + (secondChild - 1));
		holeIndex = secondChild - 1;
	}
	__push_heap(first , holeIndex , topIndex , value);
}

template <class RandomAccessIterator>
inline void push_heap(RandomAccessIterator first ,  RandomAccessIterator last)
{
	__push_heap_aux(first , last , distance_type(first),value_type(first));
}

template <class RandomAccessIterator , class Distance , class T>
inline void __push_heap_aux(RandomAccessIterator first , RandomAccessIterator last , Distance* , T*)
{
	__push_heap(first , Distance((last - first) - 1) , Distance(0) , T(*(last - 1)));
}

template <class RandomAccessIterator , class Distance , class T>
inline void __push_heap(RandomAccessIterator first , Distance holeIndex , Distance topIndex, T value)
{
	Distance parent = (holeIndex - 1) / 2;
	while (holeIndex > topIndex && *(first + parent) < value) {
		*(first + holeIndex) = *(first + parent);
		holeIndex = parent;
		parent    = (holeIndex - 1) / 2;
	}
	*(first + holeIndex) = value;
}

template <class RandomAccessIterator>
inline void pop_heap(RandomAccessIterator first , RandomAccessIterator last)
{
	__pop_heap_aux(first , last , value_type(first));
}

template <class RandomAccessIterator , class T>
inline void __pop_heap_aux(RandomAccessIterator first , RandomAccessIterator last , T* value)
{
	__pop_heap(first , last - 1 , last - 1 , T(*(last - 1)) , distance_type(first));
}

template <class RandomAccessIterator , class T , class Distance>
inline void __pop_heap(RandomAccessIterator first , RandomAccessIterator last , RandomAccessIterator result , T value , Distance*)
{
	*result = *first;
	__adjust_heap(first , Distance(0) , Distance(last - first) , value);
}

3. merge sort

归并排序在STL中的实现借用函数inplace

template <class BidirectionalIter>
void mergesort(BidirectionalIter first , BidirectionalIter last )
{
	typename iterator_traits<BidirectionalIter> :: difference_type n = distance(first , last);
	if ( n == 0 || n == 1)
		return ;
	else {
		BidirectionalIter mid = first + n / 2;
		mergesort(first , mid);
		mergesort(mid   , last);
		inplace_merge(first , mid , last);
	}
}
时间: 2024-10-24 04:49:23

STL Sort Algorithm的相关文章

stl sort分析

最近写代码,无意中发现了一个坑,关于自定义比较函数的stl sort函数的坑,于是记录下来. 先贴代码: 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 5 struct finder 6 { 7 bool operator()(int first, int second){return first <= second;} 8 } my_finder; 9 10 int main

c++ STL sort struct comp

详细解说 STL 排序(Sort) http://www.cppblog.com/mzty/archive/2005/12/15/1770.html 详细解说 STL 排序(Sort) 作者Winter 详细解说 STL 排序(Sort) 0 前言: STL,为什么你必须掌握 1 STL提供的Sort 算法 1.1 所有sort算法介绍 1.2 sort 中的比较函数 1.3 sort 的稳定性 1.4 全排序 1.5 局部排序 1.6 nth_element 指定元素排序 1.7 partit

STL sort()函数

C++之所以得到这么多人的喜欢,是因为它既具有面向对象的概念,又保持了C语言高效的特点.STL 排序算法同样需要保持高效.因此,对于不同的需求,STL提供的不同的函数,不同的函数,实现的算法又不尽相同. 1.1 所有sort算法介绍 所有的sort算法的参数都需要输入一个范围,[begin, end).这里使用的迭代器(iterator)都需是随机迭代器(RadomAccessIterator), 也就是说可以随机访问的迭代器,如:it+n什么的.(partition 和stable_parti

【转】STL算法 &lt;algorithm&gt;中各种算法解析

原文:http://blog.csdn.net/tianshuai1111/article/details/7674327 一,巡防算法 for_each(容器起始地址,容器结束地址,要执行的方法) #include <iostream> #include <algorithm> #include <vector> using namespace std; template<class T> struct plus2 { void operator()(T&

STL sort

STL的sort()算法,数据量大时采用Quick Sort,分段递归排序,一旦分段后的数据量小于某个门槛,为避免Quick Sort的递归调用带来过大的额外负荷,就改用Insertion Sort.如果递归层次过深,还会改用Heap Sort.本文先分别介绍这个三个Sort,再整合分析STL sort算法(以上三种算法的综合) -- Introspective Sorting(内省式排序). 一.Insertion Sort Insertion Sort是<算法导论>一开始就讨论的算法.它的

数据结构与算法---排序算法(Sort Algorithm)

排序算法的介绍 排序也称排序算法 (Sort Algorithm),排序是将一组数据,依指定的顺序进行排列的过程. 排序的分类 1) 内部排序: 指将需要处理的所有数据都加载 到内部存储器(内存)中进行排序. 2) 外部排序法:数据量过大,无法全部加载到内 存中,需要借助外部存储(文件等)进行 排序. 常见的排序算法分类 算法的时间复杂度 度量一个程序(算法)执行时间的两种方法 1.事后统计的方法这种方法可行, 但是有两个问题:一是要想对设计的算法的运行性能进行评测,需要实际运行该程序: 二是所

STL sort 源码解析

前言 --本文整理自<STL源码解析> 虽然源码解析的代码比较老但是核心思想并没有太多变化并且直接看源码有太多细节我又看不懂最新的. 简介 sort接受两个RandomAccessIterators(随机存储迭代器),然后将区间内的所有元素以渐増的方式由小到大重新排列,第二个版本允许用户指定一个仿函数作为排序标准,STL所有关系型容器都拥有自动排序功能,不需要sort,stack,queue,priority-queue都有特别出入口,不允许排序,剩下vector,deque和list,前两者

C++标准模板库(STL):algorithm头文件的常用函数之sort()函数

sort()-排序函数 顾名思义,sort就是用来排序的函数,它根据具体情形使用不同的排序算法,效率很高.一般来说,不推荐C语言中的qsort函数,原因是qsort用起来比较麻烦,涉及很多指针的操作.而且sort在实现中规避了经典快速排序中可能出现的会导致实际复杂度退化到O(n2)的极端情况 1. 如何使用sort排序 sort函数的使用必须加上头文件"#include<algorithm>"和"using namespace std;",其使用的方式如

STL sort函数的用法

sort在STL库中是排序函数,有时冒泡.选择等O(N^2)算法会超时时,我们可以使用STL中的快速排序O(N log N)完成排序 sort在<algorithm>库里面,原型如下: template <class RandomAccessIterator> void sort ( RandomAccessIterator first, RandomAccessIterator last ); template <class RandomAccessIterator, cl