github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/sorts/dpsortint/sort.go (about)

     1  //
     2  // based on http://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf
     3  //
     4  
     5  package dpsortint
     6  
     7  const insertionSortThreshold = 27
     8  
     9  func dataequal(data []int, i, k int) bool { return !(dataless(data, i, k) || dataless(data, k, i)) }
    10  func dataless(data []int, i, k int) bool  { return data[i] < data[k] }
    11  func dataswap(data []int, i, k int)       { data[i], data[k] = data[k], data[i] }
    12  
    13  func insertionSort(data []int, lo, hi int) {
    14      for i := lo + 1; i <= hi; i++ {
    15          for k := i; k > lo && dataless(data, k, k-1); k-- {
    16              dataswap(data, k, k-1)
    17          }
    18      }
    19  }
    20  
    21  func Sort(data []int) {
    22      sortp(data, 0, len(data)-1, 3)
    23  }
    24  
    25  func sortp(data []int, left, right int, div int) {
    26      n := right - left
    27      if n == 0 {
    28          return
    29      } else if n < insertionSortThreshold {
    30          insertionSort(data, left, right)
    31          return
    32      }
    33  
    34      third := n / div
    35      // "medians"
    36      m1 := left + third
    37      m2 := right - third
    38      if m1 <= left {
    39          m1 = left + 1
    40      }
    41      if m2 >= right {
    42          m2 = right - 1
    43      }
    44  
    45      if dataless(data, m1, m2) {
    46          dataswap(data, m1, left)
    47          dataswap(data, m2, right)
    48      } else {
    49          dataswap(data, m1, right)
    50          dataswap(data, m2, left)
    51      }
    52  
    53      // pointers
    54      less := left + 1
    55      great := right - 1
    56      // sorting
    57      for k := less; k <= great; k++ {
    58          if dataless(data, k, left) {
    59              dataswap(data, k, less)
    60              less++
    61          } else if dataless(data, right, k) {
    62              for k < great && dataless(data, right, great) {
    63                  great--
    64              }
    65              dataswap(data, k, great)
    66              great--
    67              if dataless(data, k, left) {
    68                  dataswap(data, k, less)
    69                  less++
    70              }
    71          }
    72      }
    73  
    74      // swaps
    75      dist := great - less
    76      if dist < 13 {
    77          div++
    78      }
    79  
    80      dataswap(data, less-1, left)
    81      dataswap(data, great+1, right)
    82  
    83      // subarrays
    84      sortp(data, left, less-2, div)
    85      sortp(data, great+2, right, div)
    86  
    87      // equal elements
    88      if dist > n-13 && !dataequal(data, left, right) {
    89          for k := less; k <= great; k++ {
    90              if dataequal(data, k, left) {
    91                  dataswap(data, k, less)
    92                  less++
    93              } else if dataequal(data, k, right) {
    94                  dataswap(data, k, great)
    95                  great--
    96                  if dataequal(data, k, left) {
    97                      dataswap(data, k, less)
    98                      less++
    99                  }
   100              }
   101          }
   102      }
   103      // subarray
   104      if dataless(data, left, right) {
   105          sortp(data, less, great, div)
   106      }
   107  }