将此问题移至Programmers,因为它对CS来说似乎不够理论。
的 TLDR
有没有人用昂贵的交换元素测试双枢轴快速排序性能?在这种情况下,它似乎应该大大低于标准的快速排序。
的背景故事
灵感来自最近的"问题" here on stack overflow,我决定去实施给定排序的非平凡版本(introsort,quicksort 3-way partition,中间数3个轴位选择,小块插入排序等等。
在一些研究中,我也遇到了双枢轴快速排序,which is the current implementation of quicksort in Java standard library。一般来说,它声称它总是至少和标准的快速排序一样好,并且经验测试似乎支持它。 (这是当前实施的原因。)
然而,似乎没有STL实现使用双枢轴快速排序进入内部的快速排序阶段,这让我想知道为什么。经过更多的研究,我找到了this paper。它表示,虽然双枢轴快速排序平均执行的比较减少了5%,但它的交换次数要多得多。 (大约80%以上)显然,由于Java只有原语和引用类型,因此交换总是很便宜。 (即便如此,它仅对原语使用此类,因为它不稳定)
所以我想看看是否有人已经测试了标准的quicksort vs双枢轴快速排序,当交换元素很昂贵并且数字(可能还有源码)存在时,或者我是否必须自己测试。
此问题专门针对快速排序变体。
答案 0 :(得分:1)
我在论文中对此进行了广泛的研究。 https://arxiv.org/ftp/arxiv/papers/1505/1505.00558.pdf
简短的回答是,不。当交换大型元素时,与高端版本的快速排序相比,Dual Pivot也不会表现出色。看看图22和23。
答案 1 :(得分:0)
我认为本文的QUICKSORTYAROSLAVSKIY()有三个原因并不快。
QUICKSORTYAROSLAVSKIY()的优点是从分区中排除了2个枢轴。
我设计了一种算法,使quicksort更快。因为,交换是一种冗余方法,并且当N很大时,应该在各种元素中选择一个枢轴。 More..
答案 2 :(得分:0)
如果你的目标是减少掉期数量,你应该回归到排序指针。像这样:
void sort(vector<BigClass> &data) {
//First get an array of pointers.
vector<BigClass*> temp;
temp.reserve(data.size());
for(BigClass& current : data) temp.push_back(¤t);
//Sort.
sort(temp.begin(), temp.end(), [](const BigClass* &a, const BigClass* &b){
/* some lambda to compare the pointers by the objects they point to */
});
//Move the objects.
vector<BigClass> result;
result.reserve(data.size());
for(BigClass* current : temp) result.push_back(*current);
//Update the argument
swap(result, data);
}
这可以保证精确data.size()
复制结构。你不能做得更好。