stl笔记 — sort
//from stl_algo.h(MinGW g++ 4.8.1) /** * @brief Sort the elements of a sequence using a predicate for comparison. * @ingroup sorting_algorithms * @param __first An iterator. * @param __last Another iterator. * @param __comp A comparison functor. * @return Nothing. * * Sorts the elements in the range @p [__first,__last) in ascending order, * such that @p __comp(*(i+1),*i) is false for every iterator @e i in the * range @p [__first,__last-1). * * The relative ordering of equivalent elements is not preserved, use * @p stable_sort() if this is needed. */ template <typename _RandomAccessIterator, typename _Compare> inline void sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType; // concept requirements __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<_RandomAccessIterator>) __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, _ValueType, _ValueType>) __glibcxx_requires_valid_range(__first, __last); if (__first != __last) { std::__introsort_loop(__first, __last, std::__lg(__last - __first) * 2, __comp); std::__final_insertion_sort(__first, __last, __comp); } }
一、概要
从以上内容中我们可以看出STL中sort的大概用法,首先这是一个函数模板,模板参数为_RandomAccessIterator,_Compare从函数参数列表以及注释中我们可以看出,在使用sort时我们需要提供两个随机访问迭代器用于表示待排序元素的范围[first, last)和一个用于比较元素大小的仿函数__comp,再来看到的就是该排序算法的特点:原地排序,不稳定排序。
二、原理
2.1 整体原理
原理方面,sort内部,首先是对迭代器、仿函数等参数的概念要求进行检测,接着是主算法,满足条件之后,首先进行内省排序(__introsort_loop),接着进行插入排序(__final_insertion_sort)。内省排序(__introsort_loop),前两个参数仍旧为随机访问迭代器(_RandomAccessIterator), 第三个参数为递归深度限制这里取2*x(x为以2为底对元素个数求对数的结果),第四个参数为用于比较用的仿函数__comp。插入排序的参数解释类比前边的阐述。
2.2 内省排序
template<typename _RandomAccessIterator, typename _Size, typename _Compare> void __introsort_loop(_RandomAccessIterator __first, _RandomAccessIterator __last, _Size __depth_limit, _Compare __comp) { while (__last - __first > int(_S_threshold)) { if (__depth_limit == 0) { _GLIBCXX_STD_A::partial_sort(__first, __last, __last, __comp); return; } --__depth_limit; _RandomAccessIterator __cut = std::__unguarded_partition_pivot(__first, __last, __comp); std::__introsort_loop(__cut, __last, __depth_limit, __comp); __last = __cut; } }
Introsort(内省排序)排序算法首先从快速排序开始,当递归深度达到一定深度(深度为:__lg(__last - __first) * 2)后转为堆排序,由决策树模型可知最坏情况下下界为Ω(n*lg(n)),基准点选择时采用3基准中位数选择算法从序列的第一,中间和最后一个元素取得中位数来作为基准。该算法的优点是:利用quicksort的特点进行选择基准点然后进行划分(__unguarded_partition_pivot),并且限制递归深度,这样一方面减少了性能的损失,一方面避免了运行时栈溢出,当达到相应的递归深度后采用了(partial_sort),该算法内部是采用了heapsort算法,在相应的参数范围内进行排序。平均性能较好。缺点是:针对算法的特点进行精心设计的序列仍可能使算法的运行效果不理想。STL中的sort算法的整体的优点有:综合了几种排序算法的的优点,根据一定的阀值(_S_threshold=16)顶层采用内省排序,排完序之后这时整个数组已经基本有序,我们知道对于插入排序来说当待排序序列已经基本有序时其运行速度会很快,所以综合几种排序算法后,sort的平均性能比较好。期望运行时间为 O(n*k+n*lg(n/k)) k为上述阀值_S_threshold。