由于排序策略采用了 快速排序、插入排序、堆排序,建议在阅读此文之前先学习一下这三个排序算法。
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 标准库中的源码