快速排序

  1. pub fn quick_sort<T: PartialOrd>(arr: &mut [T]) {
  2. if arr.len() > 1 {
  3. quick_sort_range(arr, 0, arr.len() - 1);
  4. }
  5. }
  6. fn quick_sort_range<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) {
  7. // 只有当元素个数大于一时才进行排序
  8. if lo < hi {
  9. let pos = partition(arr, lo, hi);
  10. // let pos = partition_random(arr, lo, hi);
  11. if pos != 0 {
  12. // 如果 pos == 0, pos - 1 会发生溢出错误
  13. quick_sort_range(arr, lo, pos - 1);
  14. }
  15. quick_sort_range(arr, pos + 1, hi);
  16. }
  17. }
  18. fn partition<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) -> usize {
  19. // 默认选取 lo 作为 pivot
  20. let pivot = lo;
  21. let (mut left, mut right) = (lo, hi);
  22. while left < right {
  23. // 找到右边第一个不大于等于 arr[pivot] 的元素
  24. while left < right && arr[right] >= arr[pivot] {
  25. right -= 1;
  26. }
  27. // 找到左边第一个不小于等于 arr[pivot] 的元素
  28. while left < right && arr[left] <= arr[pivot] {
  29. left += 1;
  30. }
  31. // 交换前面找到的两个元素
  32. if left != right {
  33. arr.swap(left, right);
  34. }
  35. }
  36. arr.swap(pivot, left);
  37. // 返回正确的分割位置
  38. left
  39. }
  40. // 随机选取 pivot 的位置
  41. fn partition_random<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) -> usize {
  42. // 在 Cargo.toml 的依赖中添加 rand 库
  43. use rand::Rng;
  44. let mut rng = rand::thread_rng();
  45. let pivot = rng.gen_range(lo..=hi);
  46. // 交换 lo 和 pivot 位置上的元素,从而间接使得 pivot = lo
  47. // 因此后序操作和 partition() 函数一致
  48. arr.swap(lo, pivot);
  49. let pivot = lo;
  50. let (mut left, mut right) = (lo, hi);
  51. while left < right {
  52. // 找到右边第一个不大于等于 arr[pivot] 的元素
  53. while left < right && arr[right] >= arr[pivot] {
  54. right -= 1;
  55. }
  56. // 找到左边第一个不小于等于 arr[pivot] 的元素
  57. while left < right && arr[left] <= arr[pivot] {
  58. left += 1;
  59. }
  60. // 交换前面找到的两个元素
  61. if left != right {
  62. arr.swap(left, right);
  63. }
  64. }
  65. arr.swap(pivot, left);
  66. // 返回正确的分割位置
  67. left
  68. }
  69. #[cfg(test)]
  70. mod tests {
  71. use super::*;
  72. #[test]
  73. fn test_empty_vec() {
  74. let mut empty_vec: Vec<String> = vec![];
  75. quick_sort(&mut empty_vec);
  76. assert_eq!(empty_vec, Vec::<String>::new());
  77. }
  78. #[test]
  79. fn test_number_vec() {
  80. let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
  81. quick_sort(&mut vec);
  82. assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
  83. }
  84. #[test]
  85. fn test_string_vec() {
  86. let mut vec = vec![
  87. String::from("Bob"),
  88. String::from("David"),
  89. String::from("Carol"),
  90. String::from("Alice"),
  91. ];
  92. quick_sort(&mut vec);
  93. assert_eq!(
  94. vec,
  95. vec![
  96. String::from("Alice"),
  97. String::from("Bob"),
  98. String::from("Carol"),
  99. String::from("David"),
  100. ]
  101. );
  102. }
  103. }