1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| func doPivot(data Interface, lo, hi int) (midlo, midhi int) { m := lo + (hi-lo)/2 if hi-lo > 40 { 如果长度大于40, 使用Tukey ninther法 s := (hi - lo) / 8 medianOfThree(data, lo, lo+s, lo+2*s) medianOfThree(data, m, m-s, m+s) medianOfThree(data, hi-1, hi-1-s, hi-1-2*s) } medianOfThree(data, lo, m, hi-1)
pivot := lo a, c := lo+1, hi-1
for ; a < c && data.Less(a, pivot); a++ { } b := a for { for ; b < c && !data.Less(pivot, b); b++ { } for ; b < c && data.Less(pivot, c-1); c-- { } if b >= c { break } data.Swap(b, c-1) b++ c-- } protect := hi-c < 5 if !protect && hi-c < (hi-lo)/4 { dups := 0 if !data.Less(pivot, hi-1) { data.Swap(c, hi-1) c++ dups++ } if !data.Less(b-1, pivot) { b-- dups++ } if !data.Less(m, pivot) { data.Swap(m, b-1) b-- dups++ } protect = dups > 1 } if protect { for { for ; a < b && !data.Less(b-1, pivot); b-- { } for ; a < b && data.Less(a, pivot); a++ { } if a >= b { break } data.Swap(a, b-1) a++ b-- } } data.Swap(pivot, b-1) return b - 1, c }
func medianOfThree(data Interface, m1, m0, m2 int) { if data.Less(m1, m0) { data.Swap(m1, m0) } if data.Less(m2, m1) { data.Swap(m2, m1) if data.Less(m1, m0) { data.Swap(m1, m0) } } }
|