排序策略 - Swift标准库源码

836 阅读1分钟

由于排序策略采用了 快速排序、插入排序、堆排序,建议在阅读此文之前先学习一下这三个排序算法。

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 标准库中的源码