github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/sort/sort.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:generate go run genzfunc.go
     6  
     7  // Package sort provides primitives for sorting slices and user-defined collections.
     8  package sort
     9  
    10  // An implementation of Interface can be sorted by the routines in this package.
    11  // The methods refer to elements of the underlying collection by integer index.
    12  type Interface interface {
    13  	// Len is the number of elements in the collection.
    14  	Len() int
    15  
    16  	// Less reports whether the element with index i
    17  	// must sort before the element with index j.
    18  	//
    19  	// If both Less(i, j) and Less(j, i) are false,
    20  	// then the elements at index i and j are considered equal.
    21  	// Sort may place equal elements in any order in the final result,
    22  	// while Stable preserves the original input order of equal elements.
    23  	//
    24  	// Less must describe a transitive ordering:
    25  	//  - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well.
    26  	//  - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well.
    27  	//
    28  	// Note that floating-point comparison (the < operator on float32 or float64 values)
    29  	// is not a transitive ordering when not-a-number (NaN) values are involved.
    30  	// See Float64Slice.Less for a correct implementation for floating-point values.
    31  	Less(i, j int) bool
    32  
    33  	// Swap swaps the elements with indexes i and j.
    34  	Swap(i, j int)
    35  }
    36  
    37  // insertionSort sorts data[a:b] using insertion sort.
    38  func insertionSort(data Interface, a, b int) {
    39  	for i := a + 1; i < b; i++ {
    40  		for j := i; j > a && data.Less(j, j-1); j-- {
    41  			data.Swap(j, j-1)
    42  		}
    43  	}
    44  }
    45  
    46  // siftDown implements the heap property on data[lo:hi].
    47  // first is an offset into the array where the root of the heap lies.
    48  func siftDown(data Interface, lo, hi, first int) {
    49  	root := lo
    50  	for {
    51  		child := 2*root + 1
    52  		if child >= hi {
    53  			break
    54  		}
    55  		if child+1 < hi && data.Less(first+child, first+child+1) {
    56  			child++
    57  		}
    58  		if !data.Less(first+root, first+child) {
    59  			return
    60  		}
    61  		data.Swap(first+root, first+child)
    62  		root = child
    63  	}
    64  }
    65  
    66  func heapSort(data Interface, a, b int) {
    67  	first := a
    68  	lo := 0
    69  	hi := b - a
    70  
    71  	// Build heap with greatest element at top.
    72  	for i := (hi - 1) / 2; i >= 0; i-- {
    73  		siftDown(data, i, hi, first)
    74  	}
    75  
    76  	// Pop elements, largest first, into end of data.
    77  	for i := hi - 1; i >= 0; i-- {
    78  		data.Swap(first, first+i)
    79  		siftDown(data, lo, i, first)
    80  	}
    81  }
    82  
    83  // Quicksort, loosely following Bentley and McIlroy,
    84  // ``Engineering a Sort Function,'' SP&E November 1993.
    85  
    86  // medianOfThree moves the median of the three values data[m0], data[m1], data[m2] into data[m1].
    87  func medianOfThree(data Interface, m1, m0, m2 int) {
    88  	// sort 3 elements
    89  	if data.Less(m1, m0) {
    90  		data.Swap(m1, m0)
    91  	}
    92  	// data[m0] <= data[m1]
    93  	if data.Less(m2, m1) {
    94  		data.Swap(m2, m1)
    95  		// data[m0] <= data[m2] && data[m1] < data[m2]
    96  		if data.Less(m1, m0) {
    97  			data.Swap(m1, m0)
    98  		}
    99  	}
   100  	// now data[m0] <= data[m1] <= data[m2]
   101  }
   102  
   103  func swapRange(data Interface, a, b, n int) {
   104  	for i := 0; i < n; i++ {
   105  		data.Swap(a+i, b+i)
   106  	}
   107  }
   108  
   109  func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
   110  	m := int(uint(lo+hi) >> 1) // Written like this to avoid integer overflow.
   111  	if hi-lo > 40 {
   112  		// Tukey's ``Ninther,'' median of three medians of three.
   113  		s := (hi - lo) / 8
   114  		medianOfThree(data, lo, lo+s, lo+2*s)
   115  		medianOfThree(data, m, m-s, m+s)
   116  		medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
   117  	}
   118  	medianOfThree(data, lo, m, hi-1)
   119  
   120  	// Invariants are:
   121  	//	data[lo] = pivot (set up by ChoosePivot)
   122  	//	data[lo < i < a] < pivot
   123  	//	data[a <= i < b] <= pivot
   124  	//	data[b <= i < c] unexamined
   125  	//	data[c <= i < hi-1] > pivot
   126  	//	data[hi-1] >= pivot
   127  	pivot := lo
   128  	a, c := lo+1, hi-1
   129  
   130  	for ; a < c && data.Less(a, pivot); a++ {
   131  	}
   132  	b := a
   133  	for {
   134  		for ; b < c && !data.Less(pivot, b); b++ { // data[b] <= pivot
   135  		}
   136  		for ; b < c && data.Less(pivot, c-1); c-- { // data[c-1] > pivot
   137  		}
   138  		if b >= c {
   139  			break
   140  		}
   141  		// data[b] > pivot; data[c-1] <= pivot
   142  		data.Swap(b, c-1)
   143  		b++
   144  		c--
   145  	}
   146  	// If hi-c<3 then there are duplicates (by property of median of nine).
   147  	// Let's be a bit more conservative, and set border to 5.
   148  	protect := hi-c < 5
   149  	if !protect && hi-c < (hi-lo)/4 {
   150  		// Lets test some points for equality to pivot
   151  		dups := 0
   152  		if !data.Less(pivot, hi-1) { // data[hi-1] = pivot
   153  			data.Swap(c, hi-1)
   154  			c++
   155  			dups++
   156  		}
   157  		if !data.Less(b-1, pivot) { // data[b-1] = pivot
   158  			b--
   159  			dups++
   160  		}
   161  		// m-lo = (hi-lo)/2 > 6
   162  		// b-lo > (hi-lo)*3/4-1 > 8
   163  		// ==> m < b ==> data[m] <= pivot
   164  		if !data.Less(m, pivot) { // data[m] = pivot
   165  			data.Swap(m, b-1)
   166  			b--
   167  			dups++
   168  		}
   169  		// if at least 2 points are equal to pivot, assume skewed distribution
   170  		protect = dups > 1
   171  	}
   172  	if protect {
   173  		// Protect against a lot of duplicates
   174  		// Add invariant:
   175  		//	data[a <= i < b] unexamined
   176  		//	data[b <= i < c] = pivot
   177  		for {
   178  			for ; a < b && !data.Less(b-1, pivot); b-- { // data[b] == pivot
   179  			}
   180  			for ; a < b && data.Less(a, pivot); a++ { // data[a] < pivot
   181  			}
   182  			if a >= b {
   183  				break
   184  			}
   185  			// data[a] == pivot; data[b-1] < pivot
   186  			data.Swap(a, b-1)
   187  			a++
   188  			b--
   189  		}
   190  	}
   191  	// Swap pivot into middle
   192  	data.Swap(pivot, b-1)
   193  	return b - 1, c
   194  }
   195  
   196  func quickSort(data Interface, a, b, maxDepth int) {
   197  	for b-a > 12 { // Use ShellSort for slices <= 12 elements
   198  		if maxDepth == 0 {
   199  			heapSort(data, a, b)
   200  			return
   201  		}
   202  		maxDepth--
   203  		mlo, mhi := doPivot(data, a, b)
   204  		// Avoiding recursion on the larger subproblem guarantees
   205  		// a stack depth of at most lg(b-a).
   206  		if mlo-a < b-mhi {
   207  			quickSort(data, a, mlo, maxDepth)
   208  			a = mhi // i.e., quickSort(data, mhi, b)
   209  		} else {
   210  			quickSort(data, mhi, b, maxDepth)
   211  			b = mlo // i.e., quickSort(data, a, mlo)
   212  		}
   213  	}
   214  	if b-a > 1 {
   215  		// Do ShellSort pass with gap 6
   216  		// It could be written in this simplified form cause b-a <= 12
   217  		for i := a + 6; i < b; i++ {
   218  			if data.Less(i, i-6) {
   219  				data.Swap(i, i-6)
   220  			}
   221  		}
   222  		insertionSort(data, a, b)
   223  	}
   224  }
   225  
   226  // Sort sorts data in ascending order as determined by the Less method.
   227  // It makes one call to data.Len to determine n and O(n*log(n)) calls to
   228  // data.Less and data.Swap. The sort is not guaranteed to be stable.
   229  func Sort(data Interface) {
   230  	n := data.Len()
   231  	quickSort(data, 0, n, maxDepth(n))
   232  }
   233  
   234  // maxDepth returns a threshold at which quicksort should switch
   235  // to heapsort. It returns 2*ceil(lg(n+1)).
   236  func maxDepth(n int) int {
   237  	var depth int
   238  	for i := n; i > 0; i >>= 1 {
   239  		depth++
   240  	}
   241  	return depth * 2
   242  }
   243  
   244  // lessSwap is a pair of Less and Swap function for use with the
   245  // auto-generated func-optimized variant of sort.go in
   246  // zfuncversion.go.
   247  type lessSwap struct {
   248  	Less func(i, j int) bool
   249  	Swap func(i, j int)
   250  }
   251  
   252  type reverse struct {
   253  	// This embedded Interface permits Reverse to use the methods of
   254  	// another Interface implementation.
   255  	Interface
   256  }
   257  
   258  // Less returns the opposite of the embedded implementation's Less method.
   259  func (r reverse) Less(i, j int) bool {
   260  	return r.Interface.Less(j, i)
   261  }
   262  
   263  // Reverse returns the reverse order for data.
   264  func Reverse(data Interface) Interface {
   265  	return &reverse{data}
   266  }
   267  
   268  // IsSorted reports whether data is sorted.
   269  func IsSorted(data Interface) bool {
   270  	n := data.Len()
   271  	for i := n - 1; i > 0; i-- {
   272  		if data.Less(i, i-1) {
   273  			return false
   274  		}
   275  	}
   276  	return true
   277  }
   278  
   279  // Convenience types for common cases
   280  
   281  // IntSlice attaches the methods of Interface to []int, sorting in increasing order.
   282  type IntSlice []int
   283  
   284  func (x IntSlice) Len() int           { return len(x) }
   285  func (x IntSlice) Less(i, j int) bool { return x[i] < x[j] }
   286  func (x IntSlice) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
   287  
   288  // Sort is a convenience method: x.Sort() calls Sort(x).
   289  func (x IntSlice) Sort() { Sort(x) }
   290  
   291  // Float64Slice implements Interface for a []float64, sorting in increasing order,
   292  // with not-a-number (NaN) values ordered before other values.
   293  type Float64Slice []float64
   294  
   295  func (x Float64Slice) Len() int { return len(x) }
   296  
   297  // Less reports whether x[i] should be ordered before x[j], as required by the sort Interface.
   298  // Note that floating-point comparison by itself is not a transitive relation: it does not
   299  // report a consistent ordering for not-a-number (NaN) values.
   300  // This implementation of Less places NaN values before any others, by using:
   301  //
   302  //	x[i] < x[j] || (math.IsNaN(x[i]) && !math.IsNaN(x[j]))
   303  //
   304  func (x Float64Slice) Less(i, j int) bool { return x[i] < x[j] || (isNaN(x[i]) && !isNaN(x[j])) }
   305  func (x Float64Slice) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
   306  
   307  // isNaN is a copy of math.IsNaN to avoid a dependency on the math package.
   308  func isNaN(f float64) bool {
   309  	return f != f
   310  }
   311  
   312  // Sort is a convenience method: x.Sort() calls Sort(x).
   313  func (x Float64Slice) Sort() { Sort(x) }
   314  
   315  // StringSlice attaches the methods of Interface to []string, sorting in increasing order.
   316  type StringSlice []string
   317  
   318  func (x StringSlice) Len() int           { return len(x) }
   319  func (x StringSlice) Less(i, j int) bool { return x[i] < x[j] }
   320  func (x StringSlice) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
   321  
   322  // Sort is a convenience method: x.Sort() calls Sort(x).
   323  func (x StringSlice) Sort() { Sort(x) }
   324  
   325  // Convenience wrappers for common cases
   326  
   327  // Ints sorts a slice of ints in increasing order.
   328  func Ints(x []int) { Sort(IntSlice(x)) }
   329  
   330  // Float64s sorts a slice of float64s in increasing order.
   331  // Not-a-number (NaN) values are ordered before other values.
   332  func Float64s(x []float64) { Sort(Float64Slice(x)) }
   333  
   334  // Strings sorts a slice of strings in increasing order.
   335  func Strings(x []string) { Sort(StringSlice(x)) }
   336  
   337  // IntsAreSorted reports whether the slice x is sorted in increasing order.
   338  func IntsAreSorted(x []int) bool { return IsSorted(IntSlice(x)) }
   339  
   340  // Float64sAreSorted reports whether the slice x is sorted in increasing order,
   341  // with not-a-number (NaN) values before any other values.
   342  func Float64sAreSorted(x []float64) bool { return IsSorted(Float64Slice(x)) }
   343  
   344  // StringsAreSorted reports whether the slice x is sorted in increasing order.
   345  func StringsAreSorted(x []string) bool { return IsSorted(StringSlice(x)) }
   346  
   347  // Notes on stable sorting:
   348  // The used algorithms are simple and provable correct on all input and use
   349  // only logarithmic additional stack space. They perform well if compared
   350  // experimentally to other stable in-place sorting algorithms.
   351  //
   352  // Remarks on other algorithms evaluated:
   353  //  - GCC's 4.6.3 stable_sort with merge_without_buffer from libstdc++:
   354  //    Not faster.
   355  //  - GCC's __rotate for block rotations: Not faster.
   356  //  - "Practical in-place mergesort" from  Jyrki Katajainen, Tomi A. Pasanen
   357  //    and Jukka Teuhola; Nordic Journal of Computing 3,1 (1996), 27-40:
   358  //    The given algorithms are in-place, number of Swap and Assignments
   359  //    grow as n log n but the algorithm is not stable.
   360  //  - "Fast Stable In-Place Sorting with O(n) Data Moves" J.I. Munro and
   361  //    V. Raman in Algorithmica (1996) 16, 115-160:
   362  //    This algorithm either needs additional 2n bits or works only if there
   363  //    are enough different elements available to encode some permutations
   364  //    which have to be undone later (so not stable on any input).
   365  //  - All the optimal in-place sorting/merging algorithms I found are either
   366  //    unstable or rely on enough different elements in each step to encode the
   367  //    performed block rearrangements. See also "In-Place Merging Algorithms",
   368  //    Denham Coates-Evely, Department of Computer Science, Kings College,
   369  //    January 2004 and the references in there.
   370  //  - Often "optimal" algorithms are optimal in the number of assignments
   371  //    but Interface has only Swap as operation.
   372  
   373  // Stable sorts data in ascending order as determined by the Less method,
   374  // while keeping the original order of equal elements.
   375  //
   376  // It makes one call to data.Len to determine n, O(n*log(n)) calls to
   377  // data.Less and O(n*log(n)*log(n)) calls to data.Swap.
   378  func Stable(data Interface) {
   379  	stable(data, data.Len())
   380  }
   381  
   382  func stable(data Interface, n int) {
   383  	blockSize := 20 // must be > 0
   384  	a, b := 0, blockSize
   385  	for b <= n {
   386  		insertionSort(data, a, b)
   387  		a = b
   388  		b += blockSize
   389  	}
   390  	insertionSort(data, a, n)
   391  
   392  	for blockSize < n {
   393  		a, b = 0, 2*blockSize
   394  		for b <= n {
   395  			symMerge(data, a, a+blockSize, b)
   396  			a = b
   397  			b += 2 * blockSize
   398  		}
   399  		if m := a + blockSize; m < n {
   400  			symMerge(data, a, m, n)
   401  		}
   402  		blockSize *= 2
   403  	}
   404  }
   405  
   406  // symMerge merges the two sorted subsequences data[a:m] and data[m:b] using
   407  // the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum
   408  // Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz
   409  // Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in
   410  // Computer Science, pages 714-723. Springer, 2004.
   411  //
   412  // Let M = m-a and N = b-n. Wolog M < N.
   413  // The recursion depth is bound by ceil(log(N+M)).
   414  // The algorithm needs O(M*log(N/M + 1)) calls to data.Less.
   415  // The algorithm needs O((M+N)*log(M)) calls to data.Swap.
   416  //
   417  // The paper gives O((M+N)*log(M)) as the number of assignments assuming a
   418  // rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation
   419  // in the paper carries through for Swap operations, especially as the block
   420  // swapping rotate uses only O(M+N) Swaps.
   421  //
   422  // symMerge assumes non-degenerate arguments: a < m && m < b.
   423  // Having the caller check this condition eliminates many leaf recursion calls,
   424  // which improves performance.
   425  func symMerge(data Interface, a, m, b int) {
   426  	// Avoid unnecessary recursions of symMerge
   427  	// by direct insertion of data[a] into data[m:b]
   428  	// if data[a:m] only contains one element.
   429  	if m-a == 1 {
   430  		// Use binary search to find the lowest index i
   431  		// such that data[i] >= data[a] for m <= i < b.
   432  		// Exit the search loop with i == b in case no such index exists.
   433  		i := m
   434  		j := b
   435  		for i < j {
   436  			h := int(uint(i+j) >> 1)
   437  			if data.Less(h, a) {
   438  				i = h + 1
   439  			} else {
   440  				j = h
   441  			}
   442  		}
   443  		// Swap values until data[a] reaches the position before i.
   444  		for k := a; k < i-1; k++ {
   445  			data.Swap(k, k+1)
   446  		}
   447  		return
   448  	}
   449  
   450  	// Avoid unnecessary recursions of symMerge
   451  	// by direct insertion of data[m] into data[a:m]
   452  	// if data[m:b] only contains one element.
   453  	if b-m == 1 {
   454  		// Use binary search to find the lowest index i
   455  		// such that data[i] > data[m] for a <= i < m.
   456  		// Exit the search loop with i == m in case no such index exists.
   457  		i := a
   458  		j := m
   459  		for i < j {
   460  			h := int(uint(i+j) >> 1)
   461  			if !data.Less(m, h) {
   462  				i = h + 1
   463  			} else {
   464  				j = h
   465  			}
   466  		}
   467  		// Swap values until data[m] reaches the position i.
   468  		for k := m; k > i; k-- {
   469  			data.Swap(k, k-1)
   470  		}
   471  		return
   472  	}
   473  
   474  	mid := int(uint(a+b) >> 1)
   475  	n := mid + m
   476  	var start, r int
   477  	if m > mid {
   478  		start = n - b
   479  		r = mid
   480  	} else {
   481  		start = a
   482  		r = m
   483  	}
   484  	p := n - 1
   485  
   486  	for start < r {
   487  		c := int(uint(start+r) >> 1)
   488  		if !data.Less(p-c, c) {
   489  			start = c + 1
   490  		} else {
   491  			r = c
   492  		}
   493  	}
   494  
   495  	end := n - start
   496  	if start < m && m < end {
   497  		rotate(data, start, m, end)
   498  	}
   499  	if a < start && start < mid {
   500  		symMerge(data, a, start, mid)
   501  	}
   502  	if mid < end && end < b {
   503  		symMerge(data, mid, end, b)
   504  	}
   505  }
   506  
   507  // rotate rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data:
   508  // Data of the form 'x u v y' is changed to 'x v u y'.
   509  // rotate performs at most b-a many calls to data.Swap,
   510  // and it assumes non-degenerate arguments: a < m && m < b.
   511  func rotate(data Interface, a, m, b int) {
   512  	i := m - a
   513  	j := b - m
   514  
   515  	for i != j {
   516  		if i > j {
   517  			swapRange(data, m-i, m, j)
   518  			i -= j
   519  		} else {
   520  			swapRange(data, m-i, m+j-i, i)
   521  			j -= i
   522  		}
   523  	}
   524  	// i == j
   525  	swapRange(data, m-i, m, i)
   526  }
   527  
   528  /*
   529  Complexity of Stable Sorting
   530  
   531  
   532  Complexity of block swapping rotation
   533  
   534  Each Swap puts one new element into its correct, final position.
   535  Elements which reach their final position are no longer moved.
   536  Thus block swapping rotation needs |u|+|v| calls to Swaps.
   537  This is best possible as each element might need a move.
   538  
   539  Pay attention when comparing to other optimal algorithms which
   540  typically count the number of assignments instead of swaps:
   541  E.g. the optimal algorithm of Dudzinski and Dydek for in-place
   542  rotations uses O(u + v + gcd(u,v)) assignments which is
   543  better than our O(3 * (u+v)) as gcd(u,v) <= u.
   544  
   545  
   546  Stable sorting by SymMerge and BlockSwap rotations
   547  
   548  SymMerg complexity for same size input M = N:
   549  Calls to Less:  O(M*log(N/M+1)) = O(N*log(2)) = O(N)
   550  Calls to Swap:  O((M+N)*log(M)) = O(2*N*log(N)) = O(N*log(N))
   551  
   552  (The following argument does not fuzz over a missing -1 or
   553  other stuff which does not impact the final result).
   554  
   555  Let n = data.Len(). Assume n = 2^k.
   556  
   557  Plain merge sort performs log(n) = k iterations.
   558  On iteration i the algorithm merges 2^(k-i) blocks, each of size 2^i.
   559  
   560  Thus iteration i of merge sort performs:
   561  Calls to Less  O(2^(k-i) * 2^i) = O(2^k) = O(2^log(n)) = O(n)
   562  Calls to Swap  O(2^(k-i) * 2^i * log(2^i)) = O(2^k * i) = O(n*i)
   563  
   564  In total k = log(n) iterations are performed; so in total:
   565  Calls to Less O(log(n) * n)
   566  Calls to Swap O(n + 2*n + 3*n + ... + (k-1)*n + k*n)
   567     = O((k/2) * k * n) = O(n * k^2) = O(n * log^2(n))
   568  
   569  
   570  Above results should generalize to arbitrary n = 2^k + p
   571  and should not be influenced by the initial insertion sort phase:
   572  Insertion sort is O(n^2) on Swap and Less, thus O(bs^2) per block of
   573  size bs at n/bs blocks:  O(bs*n) Swaps and Less during insertion sort.
   574  Merge sort iterations start at i = log(bs). With t = log(bs) constant:
   575  Calls to Less O((log(n)-t) * n + bs*n) = O(log(n)*n + (bs-t)*n)
   576     = O(n * log(n))
   577  Calls to Swap O(n * log^2(n) - (t^2+t)/2*n) = O(n * log^2(n))
   578  
   579  */