STL算法之sort
STL算的中的sort接受两个RandomAcceddIterators(随机存取迭代器)。STL的所有关系型容器都拥有自动排序功能(底层采用RB-tree),所有不需要用到sort算法。至于序列式容器stack,queue和priority-queue都有特别的出入口,不允许用户对元素排序。剩下的vector、deque和list,前两者的迭代器满足要求适合用sort算法。而list的迭代器属于BidirectionalIterators,不适合sort算法。如果要对list排序,可以使用它自己通过的成员函数sort()算法。
SGI STL的sort算法,数据量大时采用QuickSort,分段递归排序。一旦分段后的数据量小于某个门槛,为避免QuickSort的递归调用带来过大的额外负荷,就改用Insertion Sort。如果递归层次过深,还会改用Heap Sort。SGI将使用快排与插入排序的分割线设为16。
RW STL的sort算法,数据大的时候用QuickSort,小的时候用Insertion Sort。
下面是SGI STL sort的源码:
// 版本一
// 千萬注意:sort()只適用於 RandomAccessIterator
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);
}
}
// 版本一
// 注意,本函式內的許多迭代器運算動作,都只適用於RandomAccess Iterators.
template <class RandomAccessIterator, class T, class Size>
void __introsort_loop(RandomAccessIterator first,
RandomAccessIterator last, T*,
Size depth_limit) {
// 以下,__stl_threshold 是個全域常數,稍早定義為 const int 16。
while (last - first > __stl_threshold) {
if (depth_limit == 0) { // 至此,切割惡化
partial_sort(first, last, last); // 改用 heapsort
return;
}
--depth_limit;
// 以下是 median-of-three 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.
// 這種寫法可讀性較差,效率並沒有比較好。
// RW STL 採用一般教科書寫法(直觀地對左半段和右半段遞迴),較易閱讀。
}
}
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(first, last);
}
template <class RandomAccessIterator>
void __insertion_sort(RandomAccessIterator first, RandomAccessIterator last) {
if (first == last) return;
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;
}
// 版本一
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));
}