STL 中sort原始碼分析

2021-05-25 07:17:00 字數 3334 閱讀 5521

以sgi的stl為例

sort有兩種過載形式

template randomaccessiterator>

void sort(randomaccessiterator first, randomaccessiterator last);

template strictweakordering>

void sort(randomaccessiterator first, randomaccessiterator last,

strictweakordering comp);

這兩種形式都要求形隨機訪問迭代器,因此只能用於容器vector或deque,這裡我們只以第一種為例進行講解
在資料量大時,採用quick sort,分段遞迴排序,一旦分段後的資料量小於門限值時,為避免遞迴的額外開銷,便採用insertion sort。
如果遞迴的層次過深,還會使用heap sort.
對於以下的以__開頭的命名函式,表示其為被內部的其它函式呼叫,而不能被使用者直接呼叫。
首先來看插入排序
template void __insertion_sort(_randomaccessiter __first, _randomaccessiter __last)
其所呼叫的 __linear_insert如下示:
template
inline void __linear_insert(_randomaccessiter __first,
_randomaccessiter __last, _tp*)
else
__unguarded_linear_insert(__last, __val);
}
這裡需要對其進行一下說明,通常情況下在進行插入排序時,既要進行大小的比較,又要對邊界進行控制,經過上面的改進後,但只需要進
行大小的比較便可,這就是**的高明這處。
首先對要插入有序部分的元素__val與隊首的最小元素 *__first進行比較,如果__val < *__first,則只__first與 __last之間的元素向後移乙個
位置,然後將__val插入隊首。
如果__val >= *__first,則說明__val在將要新生成的有序佇列中不是最小,因此,在下面的while中不用進行界限控制,只比較元素的大小
即可。

template void __unguarded_linear_insert(_randomaccessiter __last, _tp __val) 

*__last = __val;

}

在stl中對避免快排時每次都選擇最小或最大的元素做軸,使用以下函式選擇乙個三點中值。
template inline const _tp& __median(const _tp& __a, const _tp& __b, const _tp& __c)
下面是快排中所要使用的分割函式。對[first,last)區間的元素進行分割,使用得中軸右邊的元素大於等於中軸,左邊的元素小於等於中軸,
並返回中軸所在位置。
template _randomaccessiter __unguarded_partition(_randomaccessiter __first, 

_randomaccessiter __last,

_tp __pivot) //__pivot為中軸

}

sort **如下
template inline void sort(_randomaccessiter __first, _randomaccessiter __last) 

}

基中__lg(n)用來找出2^k<=n的最大k值,用以控控制遞迴的深度。
template inline _size __lg(_size __n)
下面的是用來對區間使用快排,以達到部分有序狀態。
template void __introsort_loop(_randomaccessiter __first,

_randomaccessiter __last, _tp*,

_size __depth_limit)

--__depth_limit;

_randomaccessiter __cut =

__unguarded_partition(__first, __last,

_tp(__median(*__first,

*(__first + (__last - __first)/2),

*(__last - 1))));//使用分割函式,反回中軸

__introsort_loop(__cut, __last, (_tp*) 0, __depth_limit);//對右半部分進行遞迴排序

__last = __cut;//使尾指標指向中軸,即要對左半部分排序

}}

最後使用插入排序對各部分進行排序。
template void __final_insertion_sort(_randomaccessiter __first, 

_randomaccessiter __last)

else

__insertion_sort(__first, __last);

}

些函式先判斷元素個數是否大於16,如是大於,則先用__insertion_sort()對16個元素的子串行排序,再用__unguarded_insertion_sort()對
其餘的排序。否則直接用__insertion_sort()排序。
template inline void __unguarded_insertion_sort(_randomaccessiter __first, 

_randomaccessiter __last)

template void __unguarded_insertion_sort_aux(_randomaccessiter __first,

_randomaccessiter __last,

_tp*, _compare __comp)

template void __unguarded_linear_insert(_randomaccessiter __last, _tp __val) 

*__last = __val;

}

ps:個人感覺__final_insertion_sort()中區分區間大小是多此一舉,因為最終其呼叫的都是__unguarded_linear_insert(),其並沒用針對不
同的大小區間採用明顯不用的演算法。

《STL原始碼剖析》Sort排序分析

整體而言 sort演算法在資料量大時採用quick sort 快速排序 一旦分段後的資料量小於某個門檻,為避免quick sort的遞迴呼叫帶來過大的額外負擔,就改用insertion sort 插入排序 如果遞迴層次過深,還會改用heap sort 堆排序 先分別簡單介紹quick sort in...

STL原始碼 演算法sort

sort演算法接受兩個randomaccessiterators 隨機訪問迭代器 然後對區間內元素以漸增方式由小到大排序 另乙個版本允許使用者指定排序方式。stl的所有關聯容器都擁有自動排序功能 以為底層的rb tree是自動排序的 因此,不需要使用sort演算法。順序容器中stack queue ...

集合中sort的原始碼分析

1 不設定比較規則的sort排序 public static void sort listlist object a list.toarray arrays.sort a listiteratori list.listiterator for int j 0 j首先是給乙個list型別的集合 然後自...