为什么这种局部快速排序实现比标准库排序慢得多?

时间:2020-05-24 23:58:37

标签: sorting rust

显然,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;
    }

}

1 个答案:

答案 0 :(得分:4)

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

let pivot_idx = buffer.len() - 1;

Quicksort需要一个精心选择的枢轴来提高效率:理想情况下,枢轴应将要排序的数组分成两半。因为您选择了n - 1的枢轴 index ,所以将每个切片划分为长度为n - 1的未排序前缀,并在切片末尾将单个“ sorted”元素(以及一个空的后缀)。 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处结束的元素,而不是从此处开始的元素。 / p>

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