面对昂贵掉期的双枢轴快速排序
Dual pivot quicksort in face of expensive swaps
把这个问题转给了程序员,因为它对CS来说似乎不够理论。
TLDR
有没有人测试过使用昂贵的交换元素的双枢轴快速排序性能?在这种情况下,它的性能应该大大低于标准快速排序。
基本信息
受到最近关于堆栈溢出的"问题"的启发,我决定去实现给定排序的非平凡版本(内流排序,3向分区快速排序,3个支点选择的中位数,小块插入排序等)。
在一些研究过程中,我还发现了双枢轴快速排序,这是Java标准库中快速排序的当前实现。一般来说,它声称它总是至少和标准快速排序一样好,经验测试似乎支持它。(这就是它是当前实现的原因。)
然而,似乎没有STL实现在内敛排序的快速排序阶段使用双枢轴快速排序,这让我想知道为什么。经过更多的研究,我找到了这篇论文。它表示,虽然双枢轴快速排序执行的比较平均减少了5%,但它执行的交换却明显更多。(大约增加80%)显然,由于Java只有原语和引用类型,交换总是很便宜。(即便如此,它也只对原语使用这种排序,因为它不稳定)
所以我想看看是否有人已经测试过标准快速排序与双轴快速排序时,元素是昂贵的交换和有数字(可能源)躺在周围,或者我是否必须自己测试。
这个问题是关于快速排序变量的
我在论文中已经对此进行了广泛的研究。https://arxiv.org/ftp/arxiv/papers/1505/1505.00558.pdf
简短的回答是否定的。当交换大元素时,与高端版本的快速排序相比,Dual Pivot的性能并不好。请看图22和图23。
我认为论文的QUICKSORTYAROSLAVSKIY()不够快有3个原因。
- 很难找到一个好的支点。通常两个支点太近或太远。
- swap太多。例如,第12行中的交换是部分数组滑动。
- 插入排序实现是不实际的。论文中的Knuth算法可能是用来教学的。我不喜欢部分数组滑动。
QUICKSORTYAROSLAVSKIY()的优点是2个枢轴被排除在分区之外。
我设计了一种算法使快速排序更快。因为交换是一种冗余的方法,当N较大时,需要在各个元素中选择一个枢轴。更多. .
如果您的目标是减少交换的次数,您应该退回到排序指针。像这样:
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()
复制构造。你做得再好不过了。
- 如何修复我的快速排序实现?
- C++运行时错误与快速排序算法抛出堆栈转储错误
- 在 MIPS 中快速排序
- 不正确的比较和交换计数器输出用于快速排序功能
- 使用 std::vector C++快速排序,EXC_BAD_ACCESS代码 2
- 使用快速排序对 C++ 中的可视化工具错误进行排序
- 快速排序 - 三个中位数枢轴选择 - 某些元素顺序不正确
- 并行快速排序分区中的隔离错误
- 实现 3 路分区以实现快速排序
- 为什么这个快速排序实现给出了一个奇怪的输出
- 我的快速排序在对预排序的项目进行排序时失败,如何改进?
- 快速排序不适用于大型数组
- 快速排序;分段错误,但找不到位置?
- 快速排序函数在快速排序算法中如何工作?
- 3路随机快速排序分区功能
- 在最坏的情况下试验快速排序.它运行良好,但在最坏的情况下发生未知错误.我想
- 当给出预先排序的输入时,为什么我的快速排序实现很慢
- 我想要一个改变数组快速排序的2个数字的函数
- C++一个具有 2 个参数(___ _____,整数长度)的函数中的快速排序
- 面对昂贵掉期的双枢轴快速排序