题目:
n \sqrt{n} n段合并排序算法:
将数组 a [ 0 , n − 1 ] a[0,n-1] a[0,n−1]划分为 ⌊ n ⌋ ⌊\sqrt{n}⌋ ⌊n⌋个子数组,每个子数组有 O ( n ) O(\sqrt{n}) O(n)个元素。然后递归地对分割后的子数组进行排序,最后将所得到的 ⌊ n ⌋ ⌊\sqrt{n}⌋ ⌊n⌋个排好序的子数组合并排序。
解法:
use rand::prelude::*;
fn square_merge_sort(a: &mut Vec<usize>, start: usize, end: usize) {
let num = ((end - start + 1) as f64).sqrt() as usize;
if num > 1 {
// 前 num - 1 个子数组,数组中元素个数为 num
for i in 0..num - 1 {
square_merge_sort(a, start + i * num, start + (i + 1) * num - 1);
}
// 第 num 个子数组,数组中元素个数可能大于 num
square_merge_sort(a, start + (num - 1) * num, end);
// 进行合并
merge(a, start, end, num);
} else {
// 当 num 为 1 时进行直接排序,即子数组元素个数为 1、2、3 的情况
sort_num_equal_1(a, start, end);
}
}
fn sort_num_equal_1(a: &mut Vec<usize>, start: usize, end: usize) {
let num = end - start + 1;
// 当个数为 1 时直接返回
if num == 1 {
return;
}
// 当个数为 2 时的处理
if a[start] > a[start + 1] {
a.swap(start, start + 1);
}
if num == 3 {
if a[start] > a[start + 2] {
a.swap(start, start + 2);
}
if a[start + 1] > a[start + 2] {
a.swap(start + 1, start + 2);
}
}
}
fn merge(a: &mut Vec<usize>, start: usize, end: usize, num: usize) {
// 新建一个辅助数组
let mut tmp: Vec<usize> = Vec::new();
// 记录每一个子数组当前的索引位置,用于判断子数组是否添加完成
let mut part_index: Vec<usize> = Vec::new();
for _ in 0..num {
part_index.push(0);
}
for _ in 0..end - start + 1 {
let mut min = usize::MAX;
let mut index: usize = 0;
for i in 0..num {
// 如果子数组已经全部添加,则跳过这个子数组,直接遍历下一个子数组,这边要分是前 num 个子数组还是第 num 个子数组两种情况(因为第 num 个子数组个数不一定是 num )
if (i != num - 1 && part_index[i] == num) || (i == num - 1 && part_index[i] == end - start + 1 - (num - 1) * num) {
continue;
}
// 寻找各子数组中的最小值,并做标记是哪一个子数组
if min > a[start + i * (num) + part_index[i]] {
min = a[start + i * (num) + part_index[i]];
index = i;
}
}
// 当前有最小值的子数组索引加 1,表示当前的值已经作为最小值添加过
part_index[index] = part_index[index] + 1;
tmp.push(min);
}
// 修改原数组
for i in 0..end - start + 1 {
a[start + i] = tmp[i];
}
}
fn main() {
// 1、创建一个数组
let mut a: Vec<usize> = Vec::new();
// 2、在数据中生成 50个 0~100 的随机数
let mut rng = rand::thread_rng();
for _ in 0..50 {
a.push(rng.gen_range(0..101));
}
// 3、打印生成的原数组
for (_, num) in a.iter().enumerate() {
print!("{} ", num);
}
// 4、进行排序
let length = a.len();
square_merge_sort(&mut a, 0, length - 1);
// 5、打印排序后的数组
println!("");
for (_, num) in a.iter().enumerate() {
print!("{} ", num);
}
}