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 */