题目:

n\sqrt{n}n 段合并排序算法:

将数组a[0,n−1]a[0,n-1]a[0,n1]划分为⌊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);
    }
}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐