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