【发布时间】:2011-09-28 16:46:19
【问题描述】:
tl;dr: 是否可以有效地在双向链表上实现快速排序?我想之前的理解是,不,不是。
前几天我有机会考虑基本排序算法的迭代器要求。基本的 O(N²) 相当简单。
- 冒泡排序 - 2 个前向迭代器会做得很好,一个接一个地拖动。
- 插入排序 - 2 个双向迭代器即可。一个用于乱序元素,一个用于插入点。
- 选择排序 - 有点棘手,但前向迭代器可以解决问题。
快速排序
std::sort 中的 introsort_loop(如 gnu 标准库/hp(1994)/silicon graphics(1996) 中)要求它是 random_access。
__introsort_loop(_RandomAccessIterator __first,
_RandomAccessIterator __last,
_Size __depth_limit, _Compare __comp)
正如我所期望的那样。
现在经过仔细检查,我找不到需要快速排序的真正原因。唯一明确需要 random_access_iterators 的是 std::__median 调用,它需要计算中间元素。常规的普通快速排序不计算中位数。
分区由检查组成
if (!(__first < __last))
return __first;
对于双向检查并不是一个真正有用的检查。然而,人们应该能够用一个简单的条件
来替换之前的分区旅行(从左到右/从右到左)中的检查if ( __first == __last ) this_partitioning_is_done = true;
是否可以仅使用双向迭代器相当有效地实现快速排序?递归深度还是可以保护的。
注意。我还没有尝试过实际的实现。
【问题讨论】:
-
对于插入排序,前向迭代器就足够了。您可以使用
std::rotate和std::upper_bound的组合来实现插入,并且这两种成分只需要前向迭代器。当然仍然是 O(N^2)。
标签: c++ algorithm quicksort stl-algorithm