归并排序的Rust实现

递归版

fn main() {
    let mut a = [8, 7, 6, 5, 4, 3, 2, 1, 0];
    mergesort(&mut a);
    println!("{:?}", a);
}

use std::cmp::Ordering;

fn mergesort(array: &mut [u32]) {
    let mid = array.len() / 2;
    if mid == 0 {
        return; //base case: array.len() == 1
    }

    mergesort(&mut array[..mid]);
    mergesort(&mut array[mid..]);
    merge(array, mid);
}

fn merge(array: &mut [u32], mid: usize) {
    let mut new_array = vec![]; //use vec to keep sorted value
    let mut j = 0;
    let mut k = mid;
    for i in 0..array.len() {
        if k == array.len() || j == mid {
            //if left or right are all selected
            break;
        }
        if array[j] < array[k] {
            new_array.push(array[j]);
            j += 1;
        } else {
            new_array.push(array[k]);
            k += 1;
        }
    }
    match (j.cmp(&mid), k.cmp(&array.len())) {
        (Ordering::Equal, Ordering::Equal) => (),
        (Ordering::Less, Ordering::Equal) => {
            for i in j..mid {
                new_array.push(array[i]);
            }
        }
        (Ordering::Equal, Ordering::Less) => {
            for i in k..array.len() {
                new_array.push(array[i]);
            }
        }
        _ => (),
    }

    for i in 0..array.len() {
        array[i] = new_array[i];
    }
}

迭代队列版

自底向上的归并排序可以轻松的转换为递归表示,在由待排序的数组构成的队列中,不断取出前两个元素,合并成一个元组,放入队列后端,直至队列长度为1
以下是我龊劣的代码,,,实现思路是使用std的deque,其元素仍为deque,不断合并队首的两个队列

use std::collections::VecDeque;

fn main() {
    let mut array = [3, 7, 1, 8, 3, 6, 2, 8, 4, 0];
    iterative_merge_sort(&mut array);
    println!("{:?}", array);
}

fn iterative_merge_sort(array: &mut [u32]) {
    if array.len() == 0 || array.len() == 1 {
        return;
    }
    let mut deque = VecDeque::new();

    for i in 0..array.len() {
        //建立初始队列 ,元素为只有单个元素的队列
        deque.push_back(VecDeque::from(vec![array[i]]));
    }
    while deque.len() > 1 {
        let left = &mut deque.pop_front().unwrap();
        let right = &mut deque.pop_front().unwrap(); //当队列长度大于1时,merge队首两个元素合并并置入队尾
        deque.push_back(merge(left, right));
    }
    for i in 0..array.len() {
        array[i] = deque[0][i];     
    }

至于merge函数则试着使用递归(参考算法概论的)伪代码:

function merge(x[0..k], y[0..l])
if k = 0 return y[0..l]
if l = 0 return x[0..k]
if x[0] <= y[0]
      return x[0] + merge(x[1..k], y[0..l])
else 
      return y[0] + merge(x[0..k], y[1..l])

+号代表着连接操作

自己实现的merge:

fn merge(left: &mut VecDeque<u32>, right: &mut VecDeque<u32>) -> VecDeque<u32> {
    if left.len() == 0 {
        return right.clone();
    }
    if right.len() == 0 {
        return left.clone();
    }
    if left[0] < right[0] {
        //递归合并
        let value = left.pop_front().unwrap();
        let mut deq = merge(left, right);
        deq.push_front(value);
        deq
    } else {
        let value = right.pop_front().unwrap();
        let mut deq = merge(left, right);
        deq.push_front(value);
        deq
    }
}

代码风格诡异,毕竟是菜鸟,以后学点再改吧

posted @ 2020-09-06 10:04  Opadc'sblogs  阅读(377)  评论(0)    收藏  举报