mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-11-04 06:07:20 +08:00 
			
		
		
		
	✨ feat(rust/sorting) add insertion, merge, quick sort code (#369)
* ✨ feat(rust/sorting): add insertion_sort * ✨ feat(rust/sorting): add merge sort * ✨ feat(rust/sorting): add quick sort * 📃 docs(rust/sorting): add & correct some missing comments. * 📃 docs(rust/sorting): add & correct some missing comments.
This commit is contained in:
		@ -59,6 +59,21 @@ path = "chapter_searching/binary_search.rs"
 | 
				
			|||||||
name = "bubble_sort"
 | 
					name = "bubble_sort"
 | 
				
			||||||
path = "chapter_sorting/bubble_sort.rs"
 | 
					path = "chapter_sorting/bubble_sort.rs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run Command: cargo run --bin insertion_sort
 | 
				
			||||||
 | 
					[[bin]]
 | 
				
			||||||
 | 
					name = "insertion_sort"
 | 
				
			||||||
 | 
					path = "chapter_sorting/insertion_sort.rs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run Command: cargo run --bin quick_sort
 | 
				
			||||||
 | 
					[[bin]]
 | 
				
			||||||
 | 
					name = "quick_sort"
 | 
				
			||||||
 | 
					path = "chapter_sorting/quick_sort.rs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run Command: cargo run --bin merge_sort
 | 
				
			||||||
 | 
					[[bin]]
 | 
				
			||||||
 | 
					name = "merge_sort"
 | 
				
			||||||
 | 
					path = "chapter_sorting/merge_sort.rs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Run Command: cargo run --bin array_stack
 | 
					# Run Command: cargo run --bin array_stack
 | 
				
			||||||
[[bin]]
 | 
					[[bin]]
 | 
				
			||||||
name = "array_stack"
 | 
					name = "array_stack"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										29
									
								
								codes/rust/chapter_sorting/insertion_sort.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								codes/rust/chapter_sorting/insertion_sort.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * File: insertion_sort.rs
 | 
				
			||||||
 | 
					 * Created Time: 2023-02-13
 | 
				
			||||||
 | 
					 * Author: xBLACKICEx (xBLACKICEx@outlook.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include!("../include/include.rs");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*插入排序 */
 | 
				
			||||||
 | 
					fn insertion_sort(nums: &mut [i32]) {
 | 
				
			||||||
 | 
					    // 外循环:base = nums[1], nums[2], ..., nums[n-1]
 | 
				
			||||||
 | 
					    for i in 1..nums.len() {
 | 
				
			||||||
 | 
					        let (base, mut j) = (nums[i],  (i - 1) as i32);
 | 
				
			||||||
 | 
					        // 内循环:将 base 插入到左边的正确位置
 | 
				
			||||||
 | 
					        while j >= 0 && nums[j as usize] > base {
 | 
				
			||||||
 | 
					            nums[(j + 1) as usize] = nums[j as usize]; // 1. 将 nums[j] 向右移动一位
 | 
				
			||||||
 | 
					            j -= 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        nums[(j + 1) as usize] = base;  // 2. 将 base 赋值到正确位置
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Driver Code */
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    let mut nums = [4, 1, 3, 1, 5, 2];
 | 
				
			||||||
 | 
					    insertion_sort(&mut nums);
 | 
				
			||||||
 | 
					    print!("插入排序完成后 nums = ");
 | 
				
			||||||
 | 
					    print_util::print_array(&nums);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										57
									
								
								codes/rust/chapter_sorting/merge_sort.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								codes/rust/chapter_sorting/merge_sort.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * File: merge_sort.rs
 | 
				
			||||||
 | 
					 * Created Time: 2023-02-14
 | 
				
			||||||
 | 
					 * Author: xBLACKICEx (xBLACKICEx@outlook.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 合并左子数组和右子数组 */
 | 
				
			||||||
 | 
					// 左子数组区间 [left, mid]
 | 
				
			||||||
 | 
					// 右子数组区间 [mid + 1, right]
 | 
				
			||||||
 | 
					fn merge(nums: &mut [i32], left: usize, mid: usize, right: usize) {
 | 
				
			||||||
 | 
					    // 初始化辅助数组
 | 
				
			||||||
 | 
					    let tmp: Vec<i32> = nums[left..right + 1].to_vec();
 | 
				
			||||||
 | 
					    // 左子数组的起始索引和结束索引
 | 
				
			||||||
 | 
					    let (left_start, left_end) = (left - left, mid - left);
 | 
				
			||||||
 | 
					    // 右子数组的起始索引和结束索引
 | 
				
			||||||
 | 
					    let (right_start, right_end) = (mid + 1 - left, right-left);
 | 
				
			||||||
 | 
					    // i, j 分别指向左子数组、右子数组的首元素
 | 
				
			||||||
 | 
					    let (mut l_corrent, mut r_corrent) = (left_start, right_start);
 | 
				
			||||||
 | 
					    // 通过覆盖原数组 nums 来合并左子数组和右子数组
 | 
				
			||||||
 | 
					    for k in left..right + 1 {
 | 
				
			||||||
 | 
					        // 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
 | 
				
			||||||
 | 
					        if l_corrent > left_end {
 | 
				
			||||||
 | 
					            nums[k] = tmp[r_corrent];
 | 
				
			||||||
 | 
					            r_corrent += 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
 | 
				
			||||||
 | 
					        else if r_corrent > right_end || tmp[l_corrent] <= tmp[r_corrent] {
 | 
				
			||||||
 | 
					            nums[k] = tmp[l_corrent];
 | 
				
			||||||
 | 
					            l_corrent += 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            nums[k] = tmp[r_corrent];
 | 
				
			||||||
 | 
					            r_corrent += 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 归并排序 */
 | 
				
			||||||
 | 
					fn merge_sort(left: usize, right: usize, nums: &mut [i32]) {
 | 
				
			||||||
 | 
					    // 终止条件
 | 
				
			||||||
 | 
					    if left >= right { return; }       // 当子数组长度为 1 时终止递归
 | 
				
			||||||
 | 
					    // 划分阶段
 | 
				
			||||||
 | 
					    let mid = (left + right) / 2;     // 计算中点
 | 
				
			||||||
 | 
					    merge_sort(left, mid, nums);      // 递归左子数组
 | 
				
			||||||
 | 
					    merge_sort(mid + 1, right, nums);  // 递归右子数组
 | 
				
			||||||
 | 
					    // 合并阶段
 | 
				
			||||||
 | 
					    merge(nums, left, mid, right);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Driver Code */
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    /* 归并排序 */
 | 
				
			||||||
 | 
					    let mut nums = [7, 3, 2, 6, 0, 1, 5, 4];
 | 
				
			||||||
 | 
					    merge_sort(0, nums.len() - 1, &mut nums);
 | 
				
			||||||
 | 
					    println!("归并排序完成后 nums = {:?}", nums);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										146
									
								
								codes/rust/chapter_sorting/quick_sort.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								codes/rust/chapter_sorting/quick_sort.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,146 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * File: quick_sort.rs
 | 
				
			||||||
 | 
					 * Created Time: 2023-02-16
 | 
				
			||||||
 | 
					 * Author: xBLACKICEx (xBLACKICE@outlook.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 快速排序
 | 
				
			||||||
 | 
					struct QuickSort;
 | 
				
			||||||
 | 
					// 快速排序(中位基准数优化)
 | 
				
			||||||
 | 
					struct QuickSortMedian;
 | 
				
			||||||
 | 
					// 快速排序(尾递归优化)
 | 
				
			||||||
 | 
					struct QuickSortTailCall;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 快速排序 */
 | 
				
			||||||
 | 
					impl QuickSort {
 | 
				
			||||||
 | 
					    /* 哨兵划分 */
 | 
				
			||||||
 | 
					    fn partition(nums: &mut [i32], left: usize, right: usize) -> usize {
 | 
				
			||||||
 | 
					        // 以 nums[left] 作为基准数
 | 
				
			||||||
 | 
					        let (mut i, mut j) = (left, right);
 | 
				
			||||||
 | 
					        while i < j {
 | 
				
			||||||
 | 
					            while i < j && nums[j] >= nums[left] {
 | 
				
			||||||
 | 
					                j -= 1;           // 从右向左找首个小于基准数的元素
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            while i < j && nums[i] <= nums[left] {
 | 
				
			||||||
 | 
					                i += 1;           // 从左向右找首个大于基准数的元素
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            nums.swap(i, j); // 交换这两个元素
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        nums.swap(i, left); // 将基准数交换至两子数组的分界线
 | 
				
			||||||
 | 
					        i                        // 返回基准数的索引
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn quick_sort(left: i32, right: i32, nums: &mut [i32]) {
 | 
				
			||||||
 | 
					        // 子数组长度为 1 时终止递归
 | 
				
			||||||
 | 
					        if left >= right {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 哨兵划分
 | 
				
			||||||
 | 
					        let pivot = Self::partition(nums, left as usize, right as usize) as i32;
 | 
				
			||||||
 | 
					        // 递归左子数组、右子数组
 | 
				
			||||||
 | 
					        Self::quick_sort(left, pivot - 1, nums);
 | 
				
			||||||
 | 
					        Self::quick_sort(pivot + 1, right, nums);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 快速排序(中位基准数优化) */
 | 
				
			||||||
 | 
					impl QuickSortMedian {
 | 
				
			||||||
 | 
					    /* 选取三个元素的中位数 */
 | 
				
			||||||
 | 
					    fn median_three(nums: &mut [i32], left: usize, mid: usize, right: usize) -> usize {
 | 
				
			||||||
 | 
					        // 使用了异或操作来简化代码
 | 
				
			||||||
 | 
					        // 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
 | 
				
			||||||
 | 
					        if (nums[left] < nums[mid]) ^ (nums[left] < nums[right]) {
 | 
				
			||||||
 | 
					            return left;
 | 
				
			||||||
 | 
					        } else if (nums[mid] < nums[left]) ^ (nums[mid] < nums[right]) {
 | 
				
			||||||
 | 
					            return mid;
 | 
				
			||||||
 | 
					        } 
 | 
				
			||||||
 | 
					        right
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 哨兵划分(三数取中值) */
 | 
				
			||||||
 | 
					    fn partition(nums: &mut [i32], left: usize, right: usize) -> usize {
 | 
				
			||||||
 | 
					        // 选取三个候选元素的中位数
 | 
				
			||||||
 | 
					        let med = Self::median_three(nums, left, (left + right) / 2, right);
 | 
				
			||||||
 | 
					        // 将中位数交换至数组最左端
 | 
				
			||||||
 | 
					        nums.swap(left, med);
 | 
				
			||||||
 | 
					        // 以 nums[left] 作为基准数
 | 
				
			||||||
 | 
					        let (mut i, mut j) = (left, right);
 | 
				
			||||||
 | 
					         while i < j {
 | 
				
			||||||
 | 
					             while i < j && nums[j] >= nums[left] {
 | 
				
			||||||
 | 
					                 j -= 1;           // 从右向左找首个小于基准数的元素
 | 
				
			||||||
 | 
					             }
 | 
				
			||||||
 | 
					             while i < j && nums[i] <= nums[left] {
 | 
				
			||||||
 | 
					                 i += 1;           // 从左向右找首个大于基准数的元素
 | 
				
			||||||
 | 
					             }
 | 
				
			||||||
 | 
					             nums.swap(i, j); // 交换这两个元素
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					         nums.swap(i, left); // 将基准数交换至两子数组的分界线
 | 
				
			||||||
 | 
					         i                        // 返回基准数的索引
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn quick_sort(left: i32, right: i32, nums: &mut [i32]) {
 | 
				
			||||||
 | 
					        // 子数组长度为 1 时终止递归
 | 
				
			||||||
 | 
					        if left >= right {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 哨兵划分
 | 
				
			||||||
 | 
					        let pivot = Self::partition(nums, left as usize, right as usize) as i32;
 | 
				
			||||||
 | 
					        // 递归左子数组、右子数组
 | 
				
			||||||
 | 
					        Self::quick_sort(left, pivot - 1, nums);
 | 
				
			||||||
 | 
					        Self::quick_sort(pivot + 1, right, nums);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 快速排序(尾递归优化) */
 | 
				
			||||||
 | 
					impl QuickSortTailCall {
 | 
				
			||||||
 | 
					    /* 哨兵划分 */
 | 
				
			||||||
 | 
					    fn partition(nums: &mut [i32], left: usize, right: usize) -> usize {
 | 
				
			||||||
 | 
					        // 以 nums[left] 作为基准数
 | 
				
			||||||
 | 
					        let (mut i, mut j) = (left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while i < j {
 | 
				
			||||||
 | 
					            while i < j && nums[j] >= nums[left] {
 | 
				
			||||||
 | 
					                j -= 1;           // 从右向左找首个小于基准数的元素
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            while i < j && nums[i] <= nums[left] {
 | 
				
			||||||
 | 
					                i += 1;           // 从左向右找首个大于基准数的元素
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            nums.swap(i, j); // 交换这两个元素
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        nums.swap(i, left); // 将基准数交换至两子数组的分界线
 | 
				
			||||||
 | 
					        i                        // 返回基准数的索引
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn quick_sort(mut left: i32, mut right: i32, nums: &mut [i32]) {
 | 
				
			||||||
 | 
					        // 子数组长度为 1 时终止
 | 
				
			||||||
 | 
					        while left < right {
 | 
				
			||||||
 | 
					            // 哨兵划分操作
 | 
				
			||||||
 | 
					            let pivot = Self::partition(nums, left as usize, right as usize) as i32;
 | 
				
			||||||
 | 
					            // 对两个子数组中较短的那个执行快排
 | 
				
			||||||
 | 
					            if  pivot - left < right - pivot {
 | 
				
			||||||
 | 
					                Self::quick_sort(left, pivot - 1, nums);  // 递归排序左子数组
 | 
				
			||||||
 | 
					                left = pivot + 1;  // 剩余待排序区间为 [pivot + 1, right]
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                Self::quick_sort(pivot + 1, right, nums); // 递归排序右子数组
 | 
				
			||||||
 | 
					                right = pivot - 1; // 剩余待排序区间为 [left, pivot - 1]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    /* 快速排序 */
 | 
				
			||||||
 | 
					    let mut nums = [2, 4, 1, 0, 3, 5];
 | 
				
			||||||
 | 
					    QuickSort::quick_sort(0, (nums.len() - 1) as i32, &mut nums);
 | 
				
			||||||
 | 
					    println!("快速排序完成后 nums = {:?}", nums);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 快速排序(中位基准数优化) */
 | 
				
			||||||
 | 
					    let mut nums = [2, 4, 1, 0, 3, 5];
 | 
				
			||||||
 | 
					    QuickSortMedian::quick_sort(0, (nums.len() - 1) as i32, &mut nums);
 | 
				
			||||||
 | 
					    println!("快速排序(中位基准数优化)完成后 nums = {:?}", nums);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 快速排序(尾递归优化) */
 | 
				
			||||||
 | 
					    let mut nums = [2, 4, 1, 0, 3, 5];
 | 
				
			||||||
 | 
					    QuickSortTailCall::quick_sort(0, (nums.len() - 1) as i32, &mut nums);
 | 
				
			||||||
 | 
					    println!("快速排序(尾递归优化)完成后 nums = {:?}", nums);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user