STL的內觀排序(introsort)演算法學習筆記 (轉)
STL(Standard Template Library)的演算法據說是經過精心的。那麼在它的排序演算法方面做了哪些最佳化呢?
自從排序演算法出世以後,從平均上來說,除了在資料量極少(<=20)的的情況下其效能不如插入排序外,快速演算法的效能起碼是其他同階演算法的2到3倍,這也已經是教科書裡不爭的事實。
一個最簡單的混合演算法就是在資料量少的時候(n<20),演算法轉入插入排序,而其它時候則仍然採用快速排序,比如
void quicksort(_RanIterator __start, _RandomIterator __last)
{
while (__last - __first > __stl_threshold) {
_RandomIterator __pivot= partition(__first, __last, mean(*__first, *__last, *(__first + (__last-__first)/2));
quicksort(__first, __pivot);
__first = __pivot;
}
__insert_sort(__first, __last);
}
這裡有一個選擇,就是什麼時候做插入排序:上面的演算法是每次細分到資料量小於閾值就轉入插入排序;另外一種演算法是一旦細分到資料長度小於閾值就退出,最後彙總的時候再來一次總的插入排序。應該說這兩種演算法沒有很大的區別,但是STL使用的是後者。原因最後再說。
STL真正出彩的地方是對快速排序演算法的補充。快速 排序的特點是平均效能好,能達到O(NlgN)的效能,缺點是對於最壞情況效能會下降到O(N^2)。STL對此做的補充是引入一個遞迴計數,當遞迴深度超過一定閾值(STL設定的閾值是2lgN),則演算法轉入一個較慢的但是最壞情況也是O(NlgN)的演算法,比如堆排序(STL把堆排序推廣為partial_sort也就是部分排序)。這一演算法自身的遞迴深度,具有一定的內觀性,被稱為內觀排序(introsort--introspective sort),實際上是快速排序法的變種,是一種混合演算法。在最壞情況下能近似達到O(NlgN)的效能。實際上在最壞情況下比堆排序要差點,但是比快速排序要好得多。而其平均效能和快速排序差不多。其演算法如下:
void introsort_l(RandomIterator __first, RandomIterator __last, int m)
{
while (__last - __first > __stl_threshold) {
if (0==m) {
partial_sort(__first, __last, __last);
return;
}
RandomIterator __pivot = mean(*__first, *__last, *(__first+(__last-__first)/2));
introsort__loop(__first, __pivot);
__first = __pivot+1;
}
}
void introsort(RandomIterator __first, RandomIterator __last)
{
introsort_loop(__first, __last, __lg(__last-__first)*2);
__final_insert_sort(__first, __last);
}
STL在__final_inser_sort中玩了一個小小的加速trick。其演算法如下:
void __final_insert_sort(__first, __last)
{
if (__last - __first < __stl_threshold)
__insert_sort(__first, __last);
else {
__insert_sort(__first, __first+__stl_threshold);
__unguarded_insert_sort(__first+__std_threshold+1, __last);
}
}
我當時不太明白為什麼插入演算法還要如此,後來自己嘗試最佳化插入演算法的時候才發現在__unguarded_insert_sort的迴圈中少了一個邊界測試條件,這樣邊界測試條件從兩個降為一個。原因就是經過“粗略的”快速排序後,最小元素已經能確定就在前__stl_threshold個元素中,於是基於位置的邊界條件就可以去掉。具體參看插入排序的演算法。不再贅述。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-988340/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- STL的學習筆記之一 (轉)筆記
- 【筆記】內部排序演算法筆記排序演算法
- SGI STL學習筆記(3):copy演算法實現細節筆記演算法
- C++ 學習筆記之——STL 庫 queueC++筆記
- C++ 學習筆記之 STL 佇列C++筆記佇列
- 智慧演算法學習筆記(一) (轉)演算法筆記
- 學習筆記--- 比較排序之堆排序筆記排序
- C++學習筆記 — STL標準模板庫C++筆記
- SGI STL學習筆記(1):空間配置器(allocator)筆記
- 演算法學習筆記演算法筆記
- C#學習筆記一:深入HelloWorld內部 (轉)C#筆記
- sed學習筆記(轉)筆記
- gurb學習筆記(轉)筆記
- ANT學習筆記 (轉)筆記
- GRUB學習筆記(轉)筆記
- TreeView學習筆記 (轉)View筆記
- SGI STL學習筆記(2):traits程式設計技法筆記AI程式設計
- 我的Hook學習筆記 (轉)Hook筆記
- 我的COM學習筆記 (轉)筆記
- LMF演算法學習筆記演算法筆記
- 機器學習演算法學習筆記機器學習演算法筆記
- 匈牙利演算法學習筆記演算法筆記
- 學習筆記----KM演算法筆記演算法
- 學習筆記----RMQ演算法筆記MQ演算法
- EM演算法學習筆記演算法筆記
- Floyd演算法學習筆記演算法筆記
- Tarjan 演算法學習筆記演算法筆記
- 圖形學學習筆記二:觀測變換筆記
- 達內課程學習筆記筆記
- 資料結構學習筆記-堆排序資料結構筆記排序
- STL(二十三)排序演算法排序演算法
- 學習筆記----快速排序的java實現及其改良筆記排序Java
- 演算法學習筆記:Kosaraju演算法演算法筆記
- numpy的學習筆記\pandas學習筆記筆記
- STL學習
- stl 和 數學slide 筆記 by JeefyIDE筆記
- ctf學習筆記[轉載]筆記
- SAP BASIS學習筆記(轉)筆記