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