func check(t *testing.T, data sort.Interface, tree *Tree, ix int) int8 { node := &tree.nodes[ix] l, r := int(node._left), int(node._right) var lh, rh int8 if l != null { if data.Less(ix, l) { t.Fatalf("%d < %d", ix, l) } lh = check(t, data, tree, l) } else { lh = 0 } if r != null { if data.Less(r, ix) { t.Fatalf("%d < %d", r, ix) } rh = check(t, data, tree, r) } else { rh = 0 } bal := lh - rh if bal < -1 || bal > 1 || tree.bal(ix) != bal { t.Fatalf("height fails: %d [%d, %d]", ix, lh, rh) } return max_i8(lh, rh) + 1 }
// InsertionSort 插入排序,时间复杂度O(n^2)。 // // 这个实现是拷贝的sort包下的 insertionSort()。 func InsertionSort(data sort.Interface, start, end int) { for i := start + 1; i < end; i++ { for j := i; j > start && data.Less(j, j-1); j-- { data.Swap(j, j-1) } } }
func reverse(data sort.Interface, a, b int) { for a < b { data.Swap(a, b) a++ b-- } }
func isort(A sort.Interface, a, b int) { for j := a + 1; j < b; j++ { for i := j; i > a && A.Less(i, i-1); i-- { A.Swap(i, i-1) } } }
func heapSort(a sort.Interface) { helper := HeapHelper{a, a.Len()} heap.Init(&helper) for helper.length > 0 { heap.Pop(&helper) } }
// Insert adds in-order element of sort.Interface at index Tree.Len() // It doesn't check for equality, so duplicates are inserted in // stable order. func (t *Tree) Insert(data sort.Interface) { ix := len(t.nodes) if ix == MaxSize { panic("tree size exceed maximum") } t.nodes = append(t.nodes, node{null, null, null, 1}) if ix == 0 { t.root, t.min, t.max = 0, 0, 0 return } var dir direction cur := t.root curnode := &t.nodes[cur] for { dir = direction(!data.Less(ix, int(cur))) if curnode.link(dir) == null { break } cur = curnode.link(dir) curnode = &t.nodes[cur] } node := &t.nodes[ix] node._parent = index(cur) curnode.set_link(dir, ix) if dir == right { if cur == t.max { t.max = ix } } else if cur == t.min { t.min = ix } t.balance(cur) }
// Make a random comparison with certain probability of correctness func randLess(i, j int, cmp sort.Interface, pCorrect float64) bool { if rand.Float64() <= pCorrect { return cmp.Less(i, j) } else { return !cmp.Less(i, j) } }
// Insertion sort func insertionSort(data sort.Interface, a, b int) { for i := a + 1; i < b; i++ { for j := i; j > a && data.Less(j, j-1); j-- { data.Swap(j, j-1) } } }
func Sort(data sort.Interface) { done := make(chan bool) go parallelQuickSort(data, 0, data.Len()-1, done) <-done }
// Simple insertion sort for smaller data collections. func insertionSort(data sort.Interface, lo, hi int) { for i := lo + 1; i < hi+1; i++ { for j := i; j > lo && data.Less(j, j-1); j-- { data.Swap(j, j-1) } } }
func xcopy(data sort.Interface, i, j, k, l int) int { for i < k && j < l { data.Swap(i, j) i, j = i+1, j+1 } return i }
// Partial quicksort algorithm due to Martínez (2004), // http://www.cs.upc.edu/~conrado/research/reports/ALCOMFT-TR-03-50.pdf func partialSort(data sort.Interface, k, lo, hi int) { for hi-lo > 5 { p := medianOfThree(data, lo, hi) p = partition(data, lo, hi, p) if p < k-1 { partialSort(data, k, p+1, hi) } hi = p } // Finish off with a selection sort. if hi-lo-1 < k { k = hi - lo - 1 } for ; k > 0; k-- { min := lo for i := lo + 1; i < hi; i++ { if data.Less(i, min) { min = i } } data.Swap(lo, min) lo++ } }
func reverse(seq sort.Interface, firstIndex int) { lastIndex := seq.Len() - 1 numSwap := (lastIndex - firstIndex + 1) / 2 for i := 0; i < numSwap; i++ { seq.Swap(firstIndex+i, lastIndex-i) } }
// Shuffle sorts data in a randomized order. It uses the default // Source in math/rand, so if clients want to manipulate the outcome, // they should call the appropriate functions in math/rand. // // TODO: Add ability to use custom Sources. func Shuffle(data sort.Interface) { length := data.Len() for i := 0; i < length; i++ { i2 := rand.Intn(i + 1) data.Swap(i, i2) } }
func NewWithIndex(sorter sort.Interface) *WithIndex { n := sorter.Len() newToOld := make([]int, n) for i := range newToOld { newToOld[i] = i } return &WithIndex{sorter, newToOld} }
// Flip reverses the order of items in a sort.Interface. func Flip(data sort.Interface) { a, b := 0, data.Len()-1 for b > a { data.Swap(a, b) a++ b-- } }
// IsUniqued reports whether the elements in data are sorted and unique. func IsUniqued(data sort.Interface) bool { n := data.Len() for i := n - 1; i > 0; i-- { if !data.Less(i-1, i) { return false } } return true }
// NewSub opaquely wraps a sub-sequence of the provided sort.Interface. // NewSub(s,i,j) is semantically equivalent to s[i:j], though the underlying // implementation does not need to use a slice. // NewSub will panic unless 0 <= i <= j <= s.Len(). func NewSub(s sort.Interface, i, j int) sort.Interface { if i < 0 || j < i || j > s.Len() { panic(panicmsg) } else if v, ok := s.(sub); ok { // collapse subs of subs return sub{v.s, v.i + i, j - i} } return sub{s, i, j - i} }
func palindrome(s sort.Interface) bool { last := s.Len() - 1 for i := 0; i < last/2; i++ { if !equals(s, i, last-i) { return false } } return true }
// NewProxy sorts comp, duplicating all swaps on each item of data. // NewProxy will panic if any item in data has a different Len() than comp. func NewProxy(comp sort.Interface, data ...sort.Interface) sort.Interface { l := comp.Len() for _, d := range data { if l != d.Len() { panic(panicmsg) } } return proxy{comp, data} }
// "sort" package has "IsSorted" function, but no "IsReversed"; func isReversed(data sort.Interface) bool { n := data.Len() for i := n - 1; i > 0; i-- { if !data.Less(i, i-1) { return false } } return true }
func IsPalindrome(s sort.Interface) bool { max := s.Len() - 1 for i := 0; i < s.Len()/2; i++ { if !equal(i, max-i, s) { return false } } return true }
func sortStable(s sort.Interface) { ss := stableSort{ s: s, pos: make([]int, s.Len()), } for i := range ss.pos { ss.pos[i] = i } sort.Sort(&ss) }
// Quicksort performs a parallel quicksort on data. func Quicksort(data sort.Interface) { a, b := 0, data.Len() n := b - a maxDepth := 0 for i := n; i > 0; i >>= 1 { maxDepth++ } maxDepth *= 2 parallelSort(data, quickSortWorker, task{-maxDepth - 1, a, b}) }
func up(h sort.Interface, left int) { for { parent := (left - 1) / 2 // parent if parent == left || !h.Less(left, parent) { break } h.Swap(parent, left) left = parent } }
// Sort sorts data. // It makes one call to data.Len to determine n, and O(n*log(n)) calls to // data.Less and data.Swap. The sort is not guaranteed to be stable. func Sort(data sort.Interface) { // Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached. n := data.Len() maxDepth := 0 for i := n; i > 0; i >>= 1 { maxDepth++ } maxDepth *= 2 quickSort(data, 0, n, maxDepth, nil) }
// NewStat initializes a *Stat for recording per-element call counts. // NewStat makes a call to data.Len. func NewStat(data sort.Interface) *Stat { l := 0 if log, ok := data.(*Log); ok { l = log.I.Len() } else { l = data.Len() } return &Stat{ I: data, O: make([]struct{ Less, Swap int }, l), } }
// SymDiff performs an in-place symmetric difference on the two sets // [0:pivot] and [pivot:Len]; the resulting set will occupy [0:size]. // SymDiff is both associative and commutative. func SymDiff(data sort.Interface, pivot int) (size int) { // BUG(extemporalgenome): SymDiff currently uses a multi-pass implementation i := Inter(data, pivot) l := data.Len() b := boundspan{data, span{i, l}} sort.Sort(b) size = Uniq(b) slide(data, 0, i, size) l = i + size sort.Sort(boundspan{data, span{size, l}}) return Diff(data, size) }
// parallelSort calls the sorters with an asyncSort function that will hand // the task off to another goroutine when possible. func parallelSort(data sort.Interface, sorter sortFunc, initialTask task) { max := runtime.GOMAXPROCS(0) if MaxProcs > 0 && MaxProcs < max { max = MaxProcs } l := data.Len() if l < minParallel { max = 1 } var syncSort func(t task) syncSort = func(t task) { sorter(data, t, syncSort) } if max == 1 { syncSort(initialTask) return } wg := new(sync.WaitGroup) // buffer up one extra task to keep each cpu busy sorts := make(chan task, int(float32(max)*bufferRatio)) var asyncSort func(t task) asyncSort = func(t task) { if t.end-t.pos < minOffload { sorter(data, t, syncSort) return } wg.Add(1) select { case sorts <- t: default: sorter(data, t, asyncSort) wg.Done() } } doSortWork := func() { for task := range sorts { sorter(data, task, asyncSort) wg.Done() } } for i := 0; i < max; i++ { go doSortWork() } asyncSort(initialTask) wg.Wait() close(sorts) }
func Quicksort(sortable sort.Interface) { partition := func(sortable sort.Interface, lo, hi int) int { pivot := hi i := lo for j := lo; j < hi; j++ { if sortable.Less(j, pivot) { sortable.Swap(i, j) i++ } } sortable.Swap(i, hi) return i } var quicksortRecursive func(sortable sort.Interface, lo, hi int) quicksortRecursive = func(sortable sort.Interface, lo, hi int) { if lo < hi { p := partition(sortable, lo, hi) quicksortRecursive(sortable, lo, p-1) quicksortRecursive(sortable, p+1, hi) } } quicksortRecursive(sortable, 0, sortable.Len()-1) }