由於排序策略採用了 快速排序、插入排序、堆排序,建議在閱讀此文之前先學習一下這三個排序演算法。
func _introSort<C>(
_ elements: inout C,
subRange range: Range<C.Index>
, by areInIncreasingOrder: (C.Element, C.Element) throws -> Bool
) rethrows
where
C : MutableCollection & RandomAccessCollection
{
let count =
elements.distance(from: range.lowerBound, to: range.upperBound)
if count < 2 {
return
}
// Set max recursion depth to 2*floor(log(N)), as suggested in the introsort
// paper: http://www.cs.rpi.edu/~musser/gp/introsort.ps
let depthLimit = 2 * count._binaryLogarithm()
try _introSortImpl(
&elements,
subRange: range,
by: areInIncreasingOrder,
depthLimit: depthLimit)
}
複製程式碼
從原始碼中可見,在呼叫 _introSortImpl
方法之前,對陣列的元素取了對數 depthLimit
,並且作為引數傳遞給排序方法。
internal func _introSortImpl<C>(
_ elements: inout C,
subRange range: Range<C.Index>
,
depthLimit: Int
)
where
C : MutableCollection & RandomAccessCollection
, C.Element : Comparable {
if elements.distance(from: range.lowerBound, to: range.upperBound) < 20 {
_insertionSort(
&elements,
subRange: range
)
return
}
if depthLimit == 0 {
_heapSort(
&elements,
subRange: range
)
return
}
let partIdx: C.Index = _partition(
&elements,
subRange: range
)
_introSortImpl(
&elements,
subRange: range.lowerBound..<partIdx,
depthLimit: depthLimit &- 1)
_introSortImpl(
&elements,
subRange: partIdx..<range.upperBound,
depthLimit: depthLimit &- 1)
複製程式碼
_introSortImpl
函式是整個演算法的核心,此處定義了陣列的排序策略。
- 當陣列個數小於20時,採用直接插入排序。
depthLimt
用於快速排序時,限制排序分割槽的深度。- 當
depthLimt == 0
時,如果陣列個數小於20時,則採用直接插入排序,否則採用堆排序。
func _introSort<C>(
_ elements: inout C,
subRange range: Range<C.Index>
, by areInIncreasingOrder: (C.Element, C.Element) throws -> Bool
) rethrows
where
C : MutableCollection & RandomAccessCollection
複製程式碼
此外原始碼中有另一組一模一樣的排序演算法,最大的區別在於每個函式都多了一個引數 areInIncreasingOrder
此引數為一個閉包,是在呼叫
public mutating func sort(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows
複製程式碼
傳遞的自定義排序規則。
sort原始碼 是gyb檔案,需要處理一下,詳細操作請參考 如何閱讀 Swift 標準庫中的原始碼