排序策略 - Swift標準庫原始碼

weixin_34402408發表於2018-04-16

由於排序策略採用了 快速排序、插入排序、堆排序,建議在閱讀此文之前先學習一下這三個排序演算法。

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 標準庫中的原始碼

相關文章