码迷,mamicode.com
首页 > 其他好文 > 详细

STL Sort Algorithm

时间:2014-11-08 18:18:19      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:style   blog   io   ar   os   使用   sp   for   on   

这个星期看了侯捷先生《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);
	}
}




STL Sort Algorithm

标签:style   blog   io   ar   os   使用   sp   for   on   

原文地址:http://blog.csdn.net/u012458164/article/details/40921811

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!