void sort(first,last)
在STL当中的sort的算法,并不是一个简单的单一的算法,是一个复合的算法,里面涵盖了堆排序,快速排序和插入排序
- 当数据量比较少的时候,快速排序体现不到其优势,而且会因为使用递归带来比较大的额外开销,因此使用的是插入排序
- 当数据量比较大的时候,就会使用快速排序。但是,快速排序有一个缺点,那就是当数据量大部分有序的时候,就会导致时间复杂度倾向于O(n^2),因此,当时间复杂度有向O(n^2)倾斜的时候,就会改为使用堆排序,从而将时间复杂度最坏情况控制在O(nlogn)
- 再者,由于插入排序在大量元素有序的情况下,性能将会十分的好,因此,当快速排序到达”就差一点点就全部有序”的状态的时候,改为使用插入排序对元素进行最终的排序
因此,在stl当中的排序是这样的
1 | template<class RandomAccessIterator> |
其中,__introsort_loop
就是之前所说的堆,快排,插入排序的复合排序了
首先,我们要知道,想要知道元素要多大才是快排,又要多大才是插入排序,我们就需要一个阈值,这个阈值是一个全局的变量const int __stl_threshold = 16;
。首先,对元素进行数量上的检查,根据数量上的差别来判断是否使用快速排序。
第二点就是要检查元素是否是大部分有序的了。这个,我们可以从快排的分割上入手。因此,在理想情况下,快速排序每一次的分割都能很好的对半分层,因此,理论上在最好的情况下就需要分logn层,一旦元素大部分有序,就需要多很多次的分割,因此,我们可以为这个分割设定一个阈值,一旦超过这个阈值,就说明元素的排序并不是很理想,要使用堆排序了,这个阈值就是函数__lg(size)
了
1 | template<class Size> |
假设数组元素是40个,那么期望的分层就是5,那么我们对其的最大分割限制就是5*2;
1 | template<class RandomAccessIterator,class T,class Size> |
- 参考资料《stl源码剖析》