Merge pull request #220 from PeiLeiScott/main

modified some sort algorithms
pull/221/head
Sunface 3 years ago committed by GitHub
commit ef8e052ff0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,12 +1,27 @@
# 冒泡排序 # 冒泡排序
```rust ```rust
pub fn bubble_sort<T: Ord>(arr: &mut [T]) { pub fn bubble_sort<T: PartialOrd>(arr: &mut [T]) {
for i in 0..arr.len() { if arr.len() <= 1 {
for j in 0..arr.len() - 1 - i { return;
if arr[j] > arr[j + 1] {
arr.swap(j, j + 1);
} }
let size = arr.len();
for i in 0..(size - 1) {
// 标记当前循环是否发生元素交换
let mut swapped = false;
// 最后i个元素已经排好了顺序
for j in 1..(size - i) {
if arr[j - 1] > arr[j] {
arr.swap(j - 1, j);
swapped = true;
}
}
// 如果当前循环没有发生元素交换,说明数组已经有序
if !swapped {
break;
} }
} }
} }
@ -16,23 +31,37 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn descending() { fn test_empty_vec() {
//降序排列 let mut empty_vec: Vec<String> = vec![];
let mut ve1 = vec![6, 5, 4, 3, 2, 1]; bubble_sort(&mut empty_vec);
bubble_sort(&mut ve1); assert_eq!(empty_vec, Vec::<String>::new());
for i in 0..ve1.len() - 1 {
assert!(ve1[i] <= ve1[i + 1]);
}
} }
#[test] #[test]
fn ascending() { fn test_number_vec() {
//升序,预排序 let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
let mut ve2 = vec![1, 2, 3, 4, 5, 6]; bubble_sort(&mut vec);
bubble_sort(&mut ve2); assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
for i in 0..ve2.len() - 1 {
assert!(ve2[i] <= ve2[i + 1]);
} }
#[test]
fn test_string_vec() {
let mut vec = vec![
String::from("Bob"),
String::from("David"),
String::from("Carol"),
String::from("Alice"),
];
bubble_sort(&mut vec);
assert_eq!(
vec,
vec![
String::from("Alice"),
String::from("Bob"),
String::from("Carol"),
String::from("David"),
]
);
} }
} }
``` ```

@ -1,96 +1,38 @@
# 堆排序 # 堆排序
```rust ```rust
/// Sort a mutable slice using heap sort. pub fn heap_sort<T: PartialOrd>(arr: &mut [T]) {
/// let size = arr.len();
/// Heap sort is an in-place O(n log n) sorting algorithm. It is based on a // 构建大根堆
/// max heap, a binary tree data structure whose main feature is that for i in (0..size / 2).rev() {
/// parent nodes are always greater or equal to their child nodes. heapify(arr, i, size);
///
/// # Max Heap Implementation
///
/// A max heap can be efficiently implemented with an array.
/// For example, the binary tree:
/// ```text
/// 1
/// 2 3
/// 4 5 6 7
/// ```
///
/// ... is represented by the following array:
/// ```text
/// 1 23 4567
/// ```
///
/// Given the index `i` of a node, parent and child indices can be calculated
/// as follows:
/// ```text
/// parent(i) = (i-1) / 2
/// left_child(i) = 2*i + 1
/// right_child(i) = 2*i + 2
/// ```
/// # Algorithm
///
/// Heap sort has two steps:
/// 1. Convert the input array to a max heap.
/// 2. Partition the array into heap part and sorted part. Initially the
/// heap consists of the whole array and the sorted part is empty:
/// ```text
/// arr: [ heap |]
/// ```
///
/// Repeatedly swap the root (i.e. the largest) element of the heap with
/// the last element of the heap and increase the sorted part by one:
/// ```text
/// arr: [ root ... last | sorted ]
/// --> [ last ... | root sorted ]
/// ```
///
/// After each swap, fix the heap to make it a valid max heap again.
/// Once the heap is empty, `arr` is completely sorted.
pub fn heap_sort<T: Ord>(arr: &mut [T]) {
if arr.len() <= 1 {
return; // already sorted
} }
heapify(arr); // 每轮循环将堆顶元素(也就是最大元素)放到最后
for i in (1..size).rev() {
for end in (1..arr.len()).rev() { arr.swap(0, i);
arr.swap(0, end); // 恢复大根堆
move_down(&mut arr[..end], 0); heapify(arr, 0, i);
} }
} }
/// Convert `arr` into a max heap. fn heapify<T: PartialOrd>(arr: &mut [T], root: usize, end: usize) {
fn heapify<T: Ord>(arr: &mut [T]) { // 记录父节点和左右节点中最大元素的索引位置
let last_parent = (arr.len() - 2) / 2; let mut largest = root;
for i in (0..=last_parent).rev() {
move_down(arr, i);
}
}
/// Move the element at `root` down until `arr` is a max heap again. let left_child = 2 * root + 1;
/// if left_child < end && arr[left_child] > arr[largest] {
/// This assumes that the subtrees under `root` are valid max heaps already. largest = left_child;
fn move_down<T: Ord>(arr: &mut [T], mut root: usize) {
let last = arr.len() - 1;
loop {
let left = 2 * root + 1;
if left > last {
break;
} }
let right = left + 1;
let max = if right <= last && arr[right] > arr[left] {
right
} else {
left
};
if arr[max] > arr[root] { let right_child = left_child + 1;
arr.swap(root, max); if right_child < end && arr[right_child] > arr[largest] {
largest = right_child;
} }
root = max;
if largest != root {
arr.swap(root, largest);
heapify(arr, largest, end);
} }
} }
@ -99,45 +41,37 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn empty() { fn test_empty_vec() {
let mut arr: Vec<i32> = Vec::new(); let mut empty_vec: Vec<String> = vec![];
heap_sort(&mut arr); heap_sort(&mut empty_vec);
assert_eq!(&arr, &[]); assert_eq!(empty_vec, Vec::<String>::new());
}
#[test]
fn single_element() {
let mut arr = vec![1];
heap_sort(&mut arr);
assert_eq!(&arr, &[1]);
}
#[test]
fn sorted_array() {
let mut arr = vec![1, 2, 3, 4];
heap_sort(&mut arr);
assert_eq!(&arr, &[1, 2, 3, 4]);
}
#[test]
fn unsorted_array() {
let mut arr = vec![3, 4, 2, 1];
heap_sort(&mut arr);
assert_eq!(&arr, &[1, 2, 3, 4]);
} }
#[test] #[test]
fn odd_number_of_elements() { fn test_number_vec() {
let mut arr = vec![3, 4, 2, 1, 7]; let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
heap_sort(&mut arr); heap_sort(&mut vec);
assert_eq!(&arr, &[1, 2, 3, 4, 7]); assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
} }
#[test] #[test]
fn repeated_elements() { fn test_string_vec() {
let mut arr = vec![542, 542, 542, 542]; let mut vec = vec![
heap_sort(&mut arr); String::from("Bob"),
assert_eq!(&arr, &vec![542, 542, 542, 542]); String::from("David"),
String::from("Carol"),
String::from("Alice"),
];
heap_sort(&mut vec);
assert_eq!(
vec,
vec![
String::from("Alice"),
String::from("Bob"),
String::from("Carol"),
String::from("David"),
]
);
} }
} }
``` ```

@ -1,25 +1,27 @@
# 插入排序 # 插入排序
```rust ```rust
use std::cmp; pub fn insertion_sort<T: PartialOrd>(arr: &mut [T]) {
// 从第二个元素开始排序
/// Sorts a mutable slice using in-place insertion sort algorithm.
///
/// Time complexity is `O(n^2)`, where `n` is the number of elements.
/// Space complexity is `O(1)` as it sorts elements in-place.
pub fn insertion_sort<T>(arr: &mut [T])
where
T: cmp::PartialOrd + Copy,
{
for i in 1..arr.len() { for i in 1..arr.len() {
let cur = arr[i]; // 找到 arr[i] 该插入的位置
let mut j = i - 1; let mut j = i;
while j > 0 && arr[j - 1] > arr[j] {
while arr[j] > cur { arr.swap(j - 1, j);
arr.swap(j + 1, j); j -= 1;
if j == 0 { }
break;
} }
}
// 这里需要 T: Ord 是因为 binary_search() 方法的限制
pub fn insertion_sort_binary_search<T: Ord>(arr: &mut[T]) {
// 从第二个元素开始排序
for i in 1..arr.len() {
// 利用二分查找获取 arr[i] 应该插入的位置
let pos = arr[..i].binary_search(&arr[i]).unwrap_or_else(|pos| pos);
let mut j = i;
while j > pos {
arr.swap(j - 1, j);
j -= 1; j -= 1;
} }
} }
@ -27,49 +29,82 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::super::is_sorted; use super::*;
mod insertion_sort {
use super::*; use super::*;
#[test] #[test]
fn empty() { fn test_empty_vec() {
let mut arr: [u8; 0] = []; let mut empty_vec: Vec<String> = vec![];
insertion_sort(&mut arr); insertion_sort(&mut empty_vec);
assert!(is_sorted(&arr)); assert_eq!(empty_vec, Vec::<String>::new());
} }
#[test] #[test]
fn one_element() { fn test_number_vec() {
let mut arr: [char; 1] = ['a']; let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
insertion_sort(&mut arr); insertion_sort(&mut vec);
assert!(is_sorted(&arr)); assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
} }
#[test] #[test]
fn already_sorted() { fn test_string_vec() {
let mut arr: [&str; 3] = ["a", "b", "c"]; let mut vec = vec![
insertion_sort(&mut arr); String::from("Bob"),
assert!(is_sorted(&arr)); String::from("David"),
String::from("Carol"),
String::from("Alice"),
];
insertion_sort(&mut vec);
assert_eq!(
vec,
vec![
String::from("Alice"),
String::from("Bob"),
String::from("Carol"),
String::from("David"),
]
);
}
} }
mod insertion_sort_binary_search {
use super::*;
#[test] #[test]
fn basic() { fn test_empty_vec() {
let mut arr: [&str; 4] = ["d", "a", "c", "b"]; let mut empty_vec: Vec<String> = vec![];
insertion_sort(&mut arr); insertion_sort_binary_search(&mut empty_vec);
assert!(is_sorted(&arr)); assert_eq!(empty_vec, Vec::<String>::new());
} }
#[test] #[test]
fn odd_number_of_elements() { fn test_number_vec() {
let mut arr: Vec<&str> = vec!["d", "a", "c", "e", "b"]; let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
insertion_sort(&mut arr); insertion_sort_binary_search(&mut vec);
assert!(is_sorted(&arr)); assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
} }
#[test] #[test]
fn repeated_elements() { fn test_string_vec() {
let mut arr: Vec<usize> = vec![542, 542, 542, 542]; let mut vec = vec![
insertion_sort(&mut arr); String::from("Bob"),
assert!(is_sorted(&arr)); String::from("David"),
String::from("Carol"),
String::from("Alice"),
];
insertion_sort_binary_search(&mut vec);
assert_eq!(
vec,
vec![
String::from("Alice"),
String::from("Bob"),
String::from("Carol"),
String::from("David"),
]
);
}
} }
} }
``` ```

@ -1,64 +1,56 @@
# 归并排序 # 归并排序
```rust ```rust
fn _merge<T: Ord + Copy>(arr: &mut [T], lo: usize, mid: usize, hi: usize) { pub fn merge_sort<T>(arr: &mut [T])
// create temporary arrays to support merge where
let mut left_half = Vec::new(); T: PartialOrd + Clone + Default,
let mut right_half = Vec::new(); {
for v in arr.iter().take(mid + 1).skip(lo) { if arr.len() > 1 {
left_half.push(*v); merge_sort_range(arr, 0, arr.len() - 1);
}
for v in arr.iter().take(hi + 1).skip(mid + 1) {
right_half.push(*v);
} }
}
let lsize = left_half.len(); fn merge_sort_range<T>(arr: &mut [T], lo: usize, hi: usize)
let rsize = right_half.len(); where
T: PartialOrd + Clone + Default,
{
// 只有当元素个数大于一时才进行排序
if lo < hi {
let mid = lo + ((hi - lo) >> 1);
merge_sort_range(arr, lo, mid);
merge_sort_range(arr, mid + 1, hi);
merge_two_arrays(arr, lo, mid, hi);
}
}
// pointers to track the positions while merging // 合并两个有序数组: arr[lo..=mid], arr[mid + 1..=hi]
let mut l = 0; fn merge_two_arrays<T>(arr: &mut [T], lo: usize, mid: usize, hi: usize)
let mut r = 0; where
let mut a = lo; T: PartialOrd + Clone + Default,
{
// 这里需要 clone 数组元素
let mut arr1 = arr[lo..=mid].to_vec();
let mut arr2 = arr[mid + 1..=hi].to_vec();
// pick smaller element one by one from either left or right half let (mut i, mut j) = (0, 0);
while l < lsize && r < rsize { while i < arr1.len() && j < arr2.len() {
if left_half[l] < right_half[r] { if arr1[i] < arr2[j] {
arr[a] = left_half[l]; arr[i + j + lo] = std::mem::take(&mut arr1[i]);
l += 1; i += 1;
} else { } else {
arr[a] = right_half[r]; arr[i + j + lo] = std::mem::take(&mut arr2[j]);
r += 1; j += 1;
} }
a += 1;
} }
// put all the remaining ones while i < arr1.len() {
while l < lsize { arr[i + j + lo] = std::mem::take(&mut arr1[i]);
arr[a] = left_half[l]; i += 1;
l += 1;
a += 1;
} }
while r < rsize { while j < arr2.len() {
arr[a] = right_half[r]; arr[i + j + lo] = std::mem::take(&mut arr2[j]);
r += 1; j += 1;
a += 1;
}
}
fn _merge_sort<T: Ord + Copy>(arr: &mut [T], lo: usize, hi: usize) {
if lo < hi {
let mid = lo + (hi - lo) / 2;
_merge_sort(arr, lo, mid);
_merge_sort(arr, mid + 1, hi);
_merge(arr, lo, mid, hi);
}
}
pub fn merge_sort<T: Ord + Copy>(arr: &mut [T]) {
let len = arr.len();
if len > 1 {
_merge_sort(arr, 0, len - 1);
} }
} }
@ -67,45 +59,37 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn basic() { fn test_empty_vec() {
let mut res = vec![10, 8, 4, 3, 1, 9, 2, 7, 5, 6]; let mut empty_vec: Vec<String> = vec![];
merge_sort(&mut res); merge_sort(&mut empty_vec);
assert_eq!(res, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); assert_eq!(empty_vec, Vec::<String>::new());
}
#[test]
fn basic_string() {
let mut res = vec!["a", "bb", "d", "cc"];
merge_sort(&mut res);
assert_eq!(res, vec!["a", "bb", "cc", "d"]);
}
#[test]
fn empty() {
let mut res = Vec::<u8>::new();
merge_sort(&mut res);
assert_eq!(res, vec![]);
}
#[test]
fn one_element() {
let mut res = vec![1];
merge_sort(&mut res);
assert_eq!(res, vec![1]);
} }
#[test] #[test]
fn pre_sorted() { fn test_number_vec() {
let mut res = vec![1, 2, 3, 4]; let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
merge_sort(&mut res); merge_sort(&mut vec);
assert_eq!(res, vec![1, 2, 3, 4]); assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
} }
#[test] #[test]
fn reverse_sorted() { fn test_string_vec() {
let mut res = vec![4, 3, 2, 1]; let mut vec = vec![
merge_sort(&mut res); String::from("Bob"),
assert_eq!(res, vec![1, 2, 3, 4]); String::from("David"),
String::from("Carol"),
String::from("Alice"),
];
merge_sort(&mut vec);
assert_eq!(
vec,
vec![
String::from("Alice"),
String::from("Bob"),
String::from("Carol"),
String::from("David"),
]
);
} }
} }
``` ```

@ -1,40 +1,125 @@
# 快速排序 # 快速排序
```rust ```rust
use std::cmp::PartialOrd; pub fn quick_sort<T: PartialOrd>(arr: &mut [T]) {
if arr.len() > 1 {
quick_sort_range(arr, 0, arr.len() - 1);
}
}
fn quick_sort_range<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) {
// 只有当元素个数大于一时才进行排序
if lo < hi {
let pos = partition(arr, lo, hi);
// let pos = partition_random(arr, lo, hi);
if pos != 0 {
// 如果 pos == 0, pos - 1 会发生溢出错误
quick_sort_range(arr, lo, pos - 1);
}
quick_sort_range(arr, pos + 1, hi);
}
}
pub fn partition<T: PartialOrd>(arr: &mut [T], lo: isize, hi: isize) -> isize { fn partition<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) -> usize {
let pivot = hi as usize; // 默认选取 lo 作为 pivot
let mut i = lo - 1; let pivot = lo;
let mut j = hi;
loop { let (mut left, mut right) = (lo, hi);
i += 1; while left < right {
while arr[i as usize] < arr[pivot] { // 找到右边第一个不大于等于 arr[pivot] 的元素
i += 1; while left < right && arr[right] >= arr[pivot] {
right -= 1;
} }
j -= 1;
while j >= 0 && arr[j as usize] > arr[pivot] { // 找到左边第一个不小于等于 arr[pivot] 的元素
j -= 1; while left < right && arr[left] <= arr[pivot] {
left += 1;
} }
if i >= j {
break; // 交换前面找到的两个元素
} else { if left != right {
arr.swap(i as usize, j as usize); arr.swap(left, right);
} }
} }
arr.swap(i as usize, pivot as usize);
i arr.swap(pivot, left);
// 返回正确的分割位置
left
} }
fn _quick_sort<T: Ord>(arr: &mut [T], lo: isize, hi: isize) {
if lo < hi { // 随机选取 pivot 的位置
let p = partition(arr, lo, hi); fn partition_random<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) -> usize {
_quick_sort(arr, lo, p - 1); // 在 Cargo.toml 的依赖中添加 rand 库
_quick_sort(arr, p + 1, hi); use rand::Rng;
let mut rng = rand::thread_rng();
let pivot = rng.gen_range(lo..=hi);
// 交换 lo 和 pivot 位置上的元素,从而间接使得 pivot = lo
// 因此后序操作和 partition() 函数一致
arr.swap(lo, pivot);
let pivot = lo;
let (mut left, mut right) = (lo, hi);
while left < right {
// 找到右边第一个不大于等于 arr[pivot] 的元素
while left < right && arr[right] >= arr[pivot] {
right -= 1;
} }
// 找到左边第一个不小于等于 arr[pivot] 的元素
while left < right && arr[left] <= arr[pivot] {
left += 1;
}
// 交换前面找到的两个元素
if left != right {
arr.swap(left, right);
}
}
arr.swap(pivot, left);
// 返回正确的分割位置
left
} }
pub fn quick_sort<T: Ord>(arr: &mut [T]) {
let len = arr.len(); #[cfg(test)]
_quick_sort(arr, 0, (len - 1) as isize); mod tests {
use super::*;
#[test]
fn test_empty_vec() {
let mut empty_vec: Vec<String> = vec![];
quick_sort(&mut empty_vec);
assert_eq!(empty_vec, Vec::<String>::new());
}
#[test]
fn test_number_vec() {
let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
quick_sort(&mut vec);
assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
}
#[test]
fn test_string_vec() {
let mut vec = vec![
String::from("Bob"),
String::from("David"),
String::from("Carol"),
String::from("Alice"),
];
quick_sort(&mut vec);
assert_eq!(
vec,
vec![
String::from("Alice"),
String::from("Bob"),
String::from("Carol"),
String::from("David"),
]
);
}
} }
``` ```

@ -1,16 +1,24 @@
# 选择排序 # 选择排序
```rust ```rust
pub fn selection_sort<T: Ord>(arr: &mut [T]) { pub fn selection_sort<T: PartialOrd>(arr: &mut [T]) {
let len = arr.len(); if arr.len() <= 1 {
for left in 0..len { return;
let mut smallest = left;
for right in (left + 1)..len {
if arr[right] < arr[smallest] {
smallest = right;
} }
let size = arr.len();
for i in 0..(size - 1) {
// 找到最小元素的索引值
let mut min_index = i;
for j in (i + 1)..size {
if arr[j] < arr[min_index] {
min_index = j;
}
}
if min_index != i {
arr.swap(i, min_index);
} }
arr.swap(smallest, left);
} }
} }
@ -19,31 +27,37 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn basic() { fn test_empty_vec() {
let mut res = vec!["d", "a", "c", "b"]; let mut empty_vec: Vec<String> = vec![];
selection_sort(&mut res); selection_sort(&mut empty_vec);
assert_eq!(res, vec!["a", "b", "c", "d"]); assert_eq!(empty_vec, Vec::<String>::new());
}
#[test]
fn empty() {
let mut res = Vec::<u8>::new();
selection_sort(&mut res);
assert_eq!(res, vec![]);
} }
#[test] #[test]
fn one_element() { fn test_number_vec() {
let mut res = vec!["a"]; let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
selection_sort(&mut res); selection_sort(&mut vec);
assert_eq!(res, vec!["a"]); assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
} }
#[test] #[test]
fn pre_sorted() { fn test_string_vec() {
let mut res = vec!["a", "b", "c"]; let mut vec = vec![
selection_sort(&mut res); String::from("Bob"),
assert_eq!(res, vec!["a", "b", "c"]); String::from("David"),
String::from("Carol"),
String::from("Alice"),
];
selection_sort(&mut vec);
assert_eq!(
vec,
vec![
String::from("Alice"),
String::from("Bob"),
String::from("Carol"),
String::from("David"),
]
);
} }
} }
``` ```
Loading…
Cancel
Save