【问题标题】:Why is this partial quick sort implementation so much slower than the standard library sort?为什么这种部分快速排序实现比标准库排序慢得多?
【发布时间】:2020-05-24 23:58:37
【问题描述】:

显然,std 库的实现总是比我的要快得多,但是在快速计算机上完成 773 x 1031 图像需要 3 分钟左右。使用相同的比较器,标准库需要 4 秒来对整个图像进行排序。任何想法为什么我的代码这么慢?

fn partial_quick_sort(img: &mut Bitmap, cmp: &BoxedPixelComparator) {
    // buffer is a Vec of Pixel structs - Pixel { r: u8, g: u8, b: u8, a: u8 }
    let max_depth = img.buffer.len()/200;
    println!("{}", max_depth); // For the input image I'm testing with, this prints 3984

    let mut queue = VecDeque::new();
    queue.push_back(img.buffer.as_mut_slice());

    let mut depth = 0;
    loop {
        let buffer_opt = queue.pop_front();
        if buffer_opt.is_none() {
            break;
        }
        let buffer = buffer_opt.unwrap();
        if depth >= max_depth || buffer.len() <= 1 {
            continue;
        }
        let pivot_idx = buffer.len() - 1;

        // cmp is a comparator function, which just compares the sums of two pixels
        let (left, _pivot, right) = buffer.partition_at_index_by(pivot_idx, cmp);
        queue.push_back(left);
        queue.push_back(right);
        depth +=1;
    }

}

【问题讨论】:

  • 盲答:你忘了使用 --release ?

标签: sorting rust


【解决方案1】:

算法最大的问题是这一行:

let pivot_idx = buffer.len() - 1;

快速排序需要一个精心选择的枢轴来提高效率:理想情况下,枢轴应该将要排序的数组分成两半。因为您选择了n - 1 的枢轴index,所以您将每个切片划分为长度为n - 1 的未排序前缀和切片末尾的单个“排序”元素(以及一个空的后缀)。 The implementation of partition_at_index* actually special cases the n - 1 case,所以这个算法基本上是一个选择排序,它是 O(n²)(例如,参见 quicksort worst case condition)。

partition_at_index_by 的文档有点含糊,可能导致您出现此错误:

使用比较器函数对切片重新排序,使index 处的元素处于其最终排序位置。

“index 处的元素”是指结束index 的元素,而不是开始那里的元素。

要解决此问题,请将上面的行更改为 buffer.len() / 2。

【讨论】:

    猜你喜欢
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    • 2021-07-27
    • 1970-01-01
    • 2021-06-19
    • 2011-06-02
    • 2019-10-11
    相关资源
    最近更新 更多