Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加 冒泡排序、选择排序、插入排序、归并排序、快速排序 的Rust实现 #66

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ _book
*.iml

src/javaSortTest/target/

src/rust/target/
20 changes: 20 additions & 0 deletions 1.bubbleSort.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,23 @@ function bubbleSort($arr)
return $arr;
}
```

## 10. Rust 代码实现

```rust
fn bubble_sort<T: Ord>(slice: &mut [T]) {
for i in 1..=slice.len() {
for j in 0..(slice.len() - i) {
match slice[j].cmp(&slice[j + 1]) {
Ordering::Less | Ordering::Equal => {
// Do nothing
}
Ordering::Greater => {
slice.swap(j, j + 1);
}
}
}
}
}
```

17 changes: 17 additions & 0 deletions 2.selectionSort.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,20 @@ function selectionSort($arr)
return $arr;
}
```

## 8. Rust 代码实现

```rust
fn selection_sort<T: Ord>(slice: &mut [T]) {
for i in 0..slice.len() {
let mut selected = i;
for j in (i + 1)..slice.len() {
if slice[j] < slice[selected] {
selected = j;
}
}

slice.swap(i, selected);
}
}
```
16 changes: 16 additions & 0 deletions 3.insertionSort.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,19 @@ function insertionSort($arr)
return $arr;
}
```

## 8. Rust 代码实现

```rust
fn insertion_sort<T: Ord>(slice: &mut [T]) {
for i in 1..slice.len() {
for j in (1..=i).rev() {
if slice[j] < slice[j - 1] {
slice.swap(j, j - 1);
} else {
break;
}
}
}
}
```
141 changes: 141 additions & 0 deletions 5.mergeSort.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,144 @@ void mergeSort(vector<int>& arr, int l, int r) { // sort the range [l, r) in arr
merge(arr, l, mid, r);
}
```

## 10. Rust 代码实现

```rust
/// 实现 1:
/// Safe Rust 实现,需要大量浅复制(move),但不需要深拷贝,对primitive type排序较慢,但对没有 Copy Trait 的类型较快
fn merge_sort<T: Ord>(mut v: Vec<T>) -> Vec<T> {
if v.len() < 2 {
return v;
}

// Split the right half and sort them first
let mut right = merge_sort(v.split_off(v.len() / 2));
let mut left = merge_sort(v);

let mut result = Vec::new();

// 反向merge,因为 `Vec::remove(0)` 的复杂度是 `O(n)` 而且需要大量复制
while !left.is_empty() && !right.is_empty() {
if left.last().unwrap() > right.last().unwrap() {
result.push(left.pop().unwrap());
} else {
result.push(right.pop().unwrap());
}
}
result.extend(left.into_iter().rev());
result.extend(right.into_iter().rev());
result.reverse();

result
}


/// 实现 2:
/// Safe Rust 实现,使用相对更少的复制,但需要更多的深拷贝。Primitive type排序速度更快,需要深拷贝的类型速度更慢
fn merge_sort2<T: Ord + Clone>(v: &mut [T]) {
if v.len() < 2 {
return;
}

let mid_idx = v.len() / 2;

merge_sort2(&mut v[..mid_idx]);
merge_sort2(&mut v[mid_idx..]);

let mut temporary = Vec::with_capacity(v.len());

let mut l = 0;
let mut r = mid_idx;

while l < mid_idx && r < v.len() {
if v[l] < v[r] {
temporary.push(v[l].clone());
l += 1;
} else {
temporary.push(v[r].clone());
r += 1;
}
}
temporary.extend(v[l..mid_idx].iter().cloned());
temporary.extend(v[r..].iter().cloned());

for (item, dest) in temporary.into_iter().zip(v.iter_mut()) {
*dest = item;
}
}


/// 实现 3:
/// Unsafe Rust 实现,类似实现2,但使用 unsafe 避免了深拷贝,性能优于实现1与实现2
fn merge_sort3<T: Ord>(v: &mut [T]) {
if v.len() < 2 {
return;
}

// 可以在遇到较短的数组时使用插入排序,性能较佳。但即使不使用插入排序,此实现性能依然优于实现1与实现2
if v.len() < 32 {
insertion_sort(v);
return;
}

let mid_idx = v.len() / 2;

merge_sort3(&mut v[..mid_idx]);
merge_sort3(&mut v[mid_idx..]);

let alloc_array = |size: usize| -> *mut T {
// 等同于C中: `(T*)malloc(sizeof(T) * size)`
unsafe {
std::alloc::alloc(
std::alloc::Layout::array::<T>(size).unwrap_unchecked(),
) as *mut T
}
};
let dealloc_array = |ptr: *mut T, size: usize| unsafe {
// 等同于C中: `free(ptr)`
std::alloc::dealloc(
ptr as *mut u8,
std::alloc::Layout::array::<T>(size).unwrap_unchecked(),
)
};

let temporary = alloc_array(v.len());
let mut used_len = 0;

let mut l = 0;
let mut r = mid_idx;

unsafe {
while l < mid_idx && r < v.len() {
if v[l] < v[r] {
temporary
.add(used_len)
.copy_from_nonoverlapping(v.as_ptr().add(l), 1);
l += 1;
} else {
temporary
.add(used_len)
.copy_from_nonoverlapping(v.as_ptr().add(r), 1);
r += 1;
}
used_len += 1;
}

let left_remain = mid_idx - l;
temporary
.add(used_len)
.copy_from_nonoverlapping(v.as_ptr().add(l), left_remain);
used_len += left_remain;

let right_remain = v.len() - r;
temporary
.add(used_len)
.copy_from_nonoverlapping(v.as_ptr().add(r), right_remain);

v.as_mut_ptr().copy_from_nonoverlapping(temporary, v.len());
}

dealloc_array(temporary, v.len());
}
```
32 changes: 31 additions & 1 deletion 6.quickSort.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func swap(arr []int, i, j int) {
## 6. C++版


```C++
```cpp
//严蔚敏《数据结构》标准分割函数
Paritition1(int A[], int low, int high) {
int pivot = A[low];
Expand Down Expand Up @@ -253,3 +253,33 @@ function quickSort($arr)
return array_merge($leftArray, $rightArray);
}
```

## 9. Rust 代码实现

```rust
fn quick_sort<T: Ord>(slice: &mut [T]) {
const PIVOT: usize = 0;

match slice.len().cmp(&2) {
Ordering::Less => {}
Ordering::Equal => {
if slice[0] > slice[1] {
slice.swap(0, 1);
}
}
Ordering::Greater => {
let mut swap_point = 0;
for i in 1..slice.len() {
if slice[i] < slice[PIVOT] {
swap_point += 1;
slice.swap(swap_point, i);
}
}
slice.swap(PIVOT, swap_point);

quick_sort(&mut slice[..swap_point]);
quick_sort(&mut slice[(swap_point + 1)..]);
}
}
}
```
75 changes: 75 additions & 0 deletions src/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "rust"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

rand = "0.8"
Loading