1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use std::cmp::{Ord, Ordering};
pub fn merge_sort<T: Copy + Ord>(slice: &mut [T]) {
merge_sort_with(slice, &|left: &T, right: &T| left.cmp(&right))
}
pub fn merge_sort_with<T: Copy, F>(slice: &mut [T], compare: &F)
where
F: Fn(&T, &T) -> Ordering,
{
let slice_len = slice.len();
let middle = slice_len / 2;
if slice_len <= 1 {
return;
}
merge_sort_with(&mut slice[0..middle], compare);
merge_sort_with(&mut slice[middle..slice_len], compare);
let mut merge: Vec<T> = slice.to_vec();
merge_with(&slice[0..middle], &slice[middle..slice_len], &mut merge[..], compare);
slice.copy_from_slice(&merge);
}
fn merge_with<T: Copy, F>(left: &[T], right: &[T], merge: &mut [T], compare: F)
where
F: Fn(&T, &T) -> Ordering,
{
assert_eq!(left.len() + right.len(), merge.len());
let mut left_index = 0;
let mut right_index = 0;
let mut merged_index = 0;
while left_index < left.len() && right_index < right.len() {
if compare(&left[left_index], &right[right_index]) == Ordering::Less {
merge[merged_index] = left[left_index];
merged_index += 1;
left_index += 1;
} else {
merge[merged_index] = right[right_index];
merged_index += 1;
right_index += 1;
}
}
if left_index < left.len() {
merge[merged_index..].copy_from_slice(&left[left_index..]);
}
if right_index < right.len() {
merge[merged_index..].copy_from_slice(&right[right_index..]);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn algo_sort_merge_1() {
let mut vec = Vec::with_capacity(100);
for left_index in (0..100).rev() {
vec.push(left_index);
}
merge_sort(&mut vec);
for left_index in 0..100 {
assert_eq!(vec[left_index], left_index);
}
}
}