Timsort

算法由 xieyu567 提交

  1. use std::cmp::min;
  2. pub fn find_min_run(mut n: usize) -> usize {
  3. let mut r = 0;
  4. let minimum = 64;
  5. while n >= minimum {
  6. r |= n & 1;
  7. n >>= 1;
  8. }
  9. n + r
  10. }
  11. pub fn insert_sort<T>(arr: &mut [T], left: usize, right: usize)
  12. where T: PartialOrd + Copy, {
  13. for i in left + 1..right + 1 {
  14. let element = arr[i];
  15. let mut j = i - 1;
  16. while element < arr[j] && j >= left {
  17. arr[j + 1] = arr[j];
  18. j -= 1;
  19. }
  20. arr[j + 1] = element;
  21. }
  22. }
  23. pub fn merge<T>(arr: &mut [T], left: usize, mid: usize, right: usize)
  24. where T: PartialOrd + Copy, {
  25. let array_length1 = mid - left + 1;
  26. let array_length2 = right - mid;
  27. let left_arr = Vec::from(&arr[left..left + array_length1]);
  28. let right_arr = Vec::from(&arr[mid + 1..mid + 1 + array_length2]);
  29. let (mut i, mut j, mut k) = (0, 0, left);
  30. while j < array_length2 && i < array_length1 {
  31. if left_arr[i] <= right_arr[j] {
  32. arr[k] = left_arr[i];
  33. i += 1;
  34. } else {
  35. arr[k] = right_arr[j];
  36. j += 1
  37. }
  38. k += 1
  39. }
  40. while i < array_length1 {
  41. arr[k] = left_arr[i];
  42. k += 1;
  43. i += 1
  44. }
  45. while j < array_length2 {
  46. arr[k] = right_arr[j];
  47. k += 1;
  48. j += 1
  49. }
  50. }
  51. pub fn tim_sort<T>(arr: &mut [T])
  52. where T: PartialOrd + Copy, {
  53. let n = arr.len();
  54. let min_run = find_min_run(n);
  55. for start in (0..n).filter(|x| x % min_run == 0) {
  56. let end = min(start + min_run - 1, n - 1);
  57. insert_sort(arr, start, end)
  58. }
  59. let mut size = min_run;
  60. while size < n {
  61. for left in (0..n).filter(|x| x % (2 * size) == 0) {
  62. let mid = min(n - 1, left + size - 1);
  63. let right = min(left + 2 * size - 1, n - 1);
  64. merge(arr, left, mid, right)
  65. }
  66. size = 2 * size
  67. }
  68. }
  69. #[cfg(test)]
  70. mod tests {
  71. use super::*;
  72. #[test]
  73. fn cal_min() {
  74. let n = 189;
  75. let min_run = find_min_run(n);
  76. assert_eq!(48, min_run);
  77. assert_eq!(61, find_min_run(976));
  78. }
  79. #[test]
  80. fn insert_test() {
  81. let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
  82. insert_sort(&mut vec, 0, 9);
  83. assert_eq!(vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78], vec)
  84. }
  85. #[test]
  86. fn tim_test() {
  87. let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
  88. tim_sort(&mut vec);
  89. assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
  90. }
  91. }