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