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,13 +1,28 @@
# 冒泡排序
```rust
pub fn bubble_sort<T: Ord>(arr: &mut [T]) {
for i in 0..arr.len() {
for j in 0..arr.len() - 1 - i {
if arr[j] > arr[j + 1] {
arr.swap(j, j + 1);
pub fn bubble_sort<T: PartialOrd>(arr: &mut [T]) {
if arr.len() <= 1 {
return;
}
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::*;
#[test]
fn descending() {
//降序排列
let mut ve1 = vec![6, 5, 4, 3, 2, 1];
bubble_sort(&mut ve1);
for i in 0..ve1.len() - 1 {
assert!(ve1[i] <= ve1[i + 1]);
}
fn test_empty_vec() {
let mut empty_vec: Vec<String> = vec![];
bubble_sort(&mut empty_vec);
assert_eq!(empty_vec, Vec::<String>::new());
}
#[test]
fn ascending() {
//升序,预排序
let mut ve2 = vec![1, 2, 3, 4, 5, 6];
bubble_sort(&mut ve2);
for i in 0..ve2.len() - 1 {
assert!(ve2[i] <= ve2[i + 1]);
}
fn test_number_vec() {
let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
bubble_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"),
];
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
/// Sort a mutable slice using heap sort.
///
/// 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
/// parent nodes are always greater or equal to their child nodes.
///
/// # 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
pub fn heap_sort<T: PartialOrd>(arr: &mut [T]) {
let size = arr.len();
// 构建大根堆
for i in (0..size / 2).rev() {
heapify(arr, i, size);
}
heapify(arr);
for end in (1..arr.len()).rev() {
arr.swap(0, end);
move_down(&mut arr[..end], 0);
// 每轮循环将堆顶元素(也就是最大元素)放到最后
for i in (1..size).rev() {
arr.swap(0, i);
// 恢复大根堆
heapify(arr, 0, i);
}
}
/// Convert `arr` into a max heap.
fn heapify<T: Ord>(arr: &mut [T]) {
let last_parent = (arr.len() - 2) / 2;
for i in (0..=last_parent).rev() {
move_down(arr, i);
fn heapify<T: PartialOrd>(arr: &mut [T], root: usize, end: usize) {
// 记录父节点和左右节点中最大元素的索引位置
let mut largest = root;
let left_child = 2 * root + 1;
if left_child < end && arr[left_child] > arr[largest] {
largest = left_child;
}
}
/// Move the element at `root` down until `arr` is a max heap again.
///
/// This assumes that the subtrees under `root` are valid max heaps already.
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
};
let right_child = left_child + 1;
if right_child < end && arr[right_child] > arr[largest] {
largest = right_child;
}
if arr[max] > arr[root] {
arr.swap(root, max);
}
root = max;
if largest != root {
arr.swap(root, largest);
heapify(arr, largest, end);
}
}
@ -99,45 +41,37 @@ mod tests {
use super::*;
#[test]
fn empty() {
let mut arr: Vec<i32> = Vec::new();
heap_sort(&mut arr);
assert_eq!(&arr, &[]);
}
#[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]);
fn test_empty_vec() {
let mut empty_vec: Vec<String> = vec![];
heap_sort(&mut empty_vec);
assert_eq!(empty_vec, Vec::<String>::new());
}
#[test]
fn odd_number_of_elements() {
let mut arr = vec![3, 4, 2, 1, 7];
heap_sort(&mut arr);
assert_eq!(&arr, &[1, 2, 3, 4, 7]);
fn test_number_vec() {
let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
heap_sort(&mut vec);
assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
}
#[test]
fn repeated_elements() {
let mut arr = vec![542, 542, 542, 542];
heap_sort(&mut arr);
assert_eq!(&arr, &vec![542, 542, 542, 542]);
fn test_string_vec() {
let mut vec = vec![
String::from("Bob"),
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
use std::cmp;
/// 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,
{
pub fn insertion_sort<T: PartialOrd>(arr: &mut [T]) {
// 从第二个元素开始排序
for i in 1..arr.len() {
let cur = arr[i];
let mut j = i - 1;
// 找到 arr[i] 该插入的位置
let mut j = i;
while j > 0 && arr[j - 1] > arr[j] {
arr.swap(j - 1, j);
j -= 1;
}
}
}
while arr[j] > cur {
arr.swap(j + 1, j);
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;
}
}
@ -27,49 +29,82 @@ where
#[cfg(test)]
mod tests {
use super::super::is_sorted;
use super::*;
#[test]
fn empty() {
let mut arr: [u8; 0] = [];
insertion_sort(&mut arr);
assert!(is_sorted(&arr));
}
mod insertion_sort {
use super::*;
#[test]
fn one_element() {
let mut arr: [char; 1] = ['a'];
insertion_sort(&mut arr);
assert!(is_sorted(&arr));
}
#[test]
fn already_sorted() {
let mut arr: [&str; 3] = ["a", "b", "c"];
insertion_sort(&mut arr);
assert!(is_sorted(&arr));
}
#[test]
fn basic() {
let mut arr: [&str; 4] = ["d", "a", "c", "b"];
insertion_sort(&mut arr);
assert!(is_sorted(&arr));
}
#[test]
fn odd_number_of_elements() {
let mut arr: Vec<&str> = vec!["d", "a", "c", "e", "b"];
insertion_sort(&mut arr);
assert!(is_sorted(&arr));
#[test]
fn test_empty_vec() {
let mut empty_vec: Vec<String> = vec![];
insertion_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];
insertion_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"),
];
insertion_sort(&mut vec);
assert_eq!(
vec,
vec![
String::from("Alice"),
String::from("Bob"),
String::from("Carol"),
String::from("David"),
]
);
}
}
#[test]
fn repeated_elements() {
let mut arr: Vec<usize> = vec![542, 542, 542, 542];
insertion_sort(&mut arr);
assert!(is_sorted(&arr));
mod insertion_sort_binary_search {
use super::*;
#[test]
fn test_empty_vec() {
let mut empty_vec: Vec<String> = vec![];
insertion_sort_binary_search(&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];
insertion_sort_binary_search(&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"),
];
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
fn _merge<T: Ord + Copy>(arr: &mut [T], lo: usize, mid: usize, hi: usize) {
// create temporary arrays to support merge
let mut left_half = Vec::new();
let mut right_half = Vec::new();
for v in arr.iter().take(mid + 1).skip(lo) {
left_half.push(*v);
}
for v in arr.iter().take(hi + 1).skip(mid + 1) {
right_half.push(*v);
pub fn merge_sort<T>(arr: &mut [T])
where
T: PartialOrd + Clone + Default,
{
if arr.len() > 1 {
merge_sort_range(arr, 0, arr.len() - 1);
}
}
let lsize = left_half.len();
let rsize = right_half.len();
fn merge_sort_range<T>(arr: &mut [T], lo: usize, hi: usize)
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
let mut l = 0;
let mut r = 0;
let mut a = lo;
// 合并两个有序数组: arr[lo..=mid], arr[mid + 1..=hi]
fn merge_two_arrays<T>(arr: &mut [T], lo: usize, mid: usize, hi: usize)
where
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
while l < lsize && r < rsize {
if left_half[l] < right_half[r] {
arr[a] = left_half[l];
l += 1;
let (mut i, mut j) = (0, 0);
while i < arr1.len() && j < arr2.len() {
if arr1[i] < arr2[j] {
arr[i + j + lo] = std::mem::take(&mut arr1[i]);
i += 1;
} else {
arr[a] = right_half[r];
r += 1;
arr[i + j + lo] = std::mem::take(&mut arr2[j]);
j += 1;
}
a += 1;
}
// put all the remaining ones
while l < lsize {
arr[a] = left_half[l];
l += 1;
a += 1;
while i < arr1.len() {
arr[i + j + lo] = std::mem::take(&mut arr1[i]);
i += 1;
}
while r < rsize {
arr[a] = right_half[r];
r += 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);
while j < arr2.len() {
arr[i + j + lo] = std::mem::take(&mut arr2[j]);
j += 1;
}
}
@ -67,45 +59,37 @@ mod tests {
use super::*;
#[test]
fn basic() {
let mut res = vec![10, 8, 4, 3, 1, 9, 2, 7, 5, 6];
merge_sort(&mut res);
assert_eq!(res, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}
#[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]);
fn test_empty_vec() {
let mut empty_vec: Vec<String> = vec![];
merge_sort(&mut empty_vec);
assert_eq!(empty_vec, Vec::<String>::new());
}
#[test]
fn pre_sorted() {
let mut res = vec![1, 2, 3, 4];
merge_sort(&mut res);
assert_eq!(res, vec![1, 2, 3, 4]);
fn test_number_vec() {
let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
merge_sort(&mut vec);
assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
}
#[test]
fn reverse_sorted() {
let mut res = vec![4, 3, 2, 1];
merge_sort(&mut res);
assert_eq!(res, vec![1, 2, 3, 4]);
fn test_string_vec() {
let mut vec = vec![
String::from("Bob"),
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
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 {
let pivot = hi as usize;
let mut i = lo - 1;
let mut j = hi;
fn partition<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) -> usize {
// 默认选取 lo 作为 pivot
let pivot = lo;
loop {
i += 1;
while arr[i as usize] < arr[pivot] {
i += 1;
let (mut left, mut right) = (lo, hi);
while left < right {
// 找到右边第一个不大于等于 arr[pivot] 的元素
while left < right && arr[right] >= arr[pivot] {
right -= 1;
}
j -= 1;
while j >= 0 && arr[j as usize] > arr[pivot] {
j -= 1;
// 找到左边第一个不小于等于 arr[pivot] 的元素
while left < right && arr[left] <= arr[pivot] {
left += 1;
}
if i >= j {
break;
} else {
arr.swap(i as usize, j as usize);
// 交换前面找到的两个元素
if left != right {
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 {
let p = partition(arr, lo, hi);
_quick_sort(arr, lo, p - 1);
_quick_sort(arr, p + 1, hi);
// 随机选取 pivot 的位置
fn partition_random<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) -> usize {
// 在 Cargo.toml 的依赖中添加 rand 库
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();
_quick_sort(arr, 0, (len - 1) as isize);
#[cfg(test)]
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
pub fn selection_sort<T: Ord>(arr: &mut [T]) {
let len = arr.len();
for left in 0..len {
let mut smallest = left;
for right in (left + 1)..len {
if arr[right] < arr[smallest] {
smallest = right;
pub fn selection_sort<T: PartialOrd>(arr: &mut [T]) {
if arr.len() <= 1 {
return;
}
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;
}
}
arr.swap(smallest, left);
if min_index != i {
arr.swap(i, min_index);
}
}
}
@ -19,31 +27,37 @@ mod tests {
use super::*;
#[test]
fn basic() {
let mut res = vec!["d", "a", "c", "b"];
selection_sort(&mut res);
assert_eq!(res, vec!["a", "b", "c", "d"]);
}
#[test]
fn empty() {
let mut res = Vec::<u8>::new();
selection_sort(&mut res);
assert_eq!(res, vec![]);
fn test_empty_vec() {
let mut empty_vec: Vec<String> = vec![];
selection_sort(&mut empty_vec);
assert_eq!(empty_vec, Vec::<String>::new());
}
#[test]
fn one_element() {
let mut res = vec!["a"];
selection_sort(&mut res);
assert_eq!(res, vec!["a"]);
fn test_number_vec() {
let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
selection_sort(&mut vec);
assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
}
#[test]
fn pre_sorted() {
let mut res = vec!["a", "b", "c"];
selection_sort(&mut res);
assert_eq!(res, vec!["a", "b", "c"]);
fn test_string_vec() {
let mut vec = vec![
String::from("Bob"),
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