std::partition quick sort implementation
std::partition quick sort implementation
我认为我在下面的实现是有效的,但显然没有。关于使用std::partition
的这种快速排序实现有什么问题的任何想法?我有一个使用nth_element版本的版本,其代码与此非常相似且更简单。
template <typename It>
void quickSort (const It& lowerIt, const It& upperIt)
{
auto d = upperIt - lowerIt ;
if ( d < 2 )
return;
auto midIt = lowerIt + d / 2;
using T = typename std::iterator_traits<It>::value_type;
T midValue = *midIt;
auto pIt = std::partition ( lowerIt, upperIt, [midValue](T i) { return i < midValue; } );
quickSort( lowerIt, pIt );
quickSort( pIt + 1, upperIt );
}
使用分区:
以前:
83, 86, 77, 15, 93, 35, 86, 92, 49, 21,
后:
21, 15, 77, 35, 49, 83, 86, 92, 86, 93,
不能保证枢轴元素将位于位置 pIt
。在大多数情况下,它不会。因此,您应该按如下方式更改算法:
- 选择透视元素 将
- 枢轴元素与
*std::prev(upperIt)
交换 - 在范围
[lowerIt, std::prev(upperIt))
上使用std::partition
- 将
pIt
与*std::prev(upperIt)
交换 - 像在代码中一样递归调用快速排序
下面是代码的固定版本:
template <typename It>
void quickSort(It lowerIt, It upperIt)
{
using std::swap;
auto size = std::distance(lowerIt, upperIt);
if (size > 1) {
auto p = std::prev(upperIt);
swap(*std::next(lowerIt, size / 2), *p);
auto q = std::partition(lowerIt, p, [p](decltype(*p) v) { return v < *p; });
swap(*q, *p);
quickSort(lowerIt, q);
quickSort(std::next(q), upperIt);
}
}
你的代码有几个严重的问题。让我们单独考虑它们。
首先,如果你选择作为枢轴的项恰好是集合中最小的,你会得到无限递归——它会把所有的元素都放到上分区中,但是当它尝试对上层分区进行排序时,它会以相同的顺序获得相同的元素,将它们全部放在上层分区中并无限重复。
消除这种情况的最常见方法是使用三个枢轴选择的中位数。这(几乎(保证至少有一个项目比透视小,一个项目比透视大,所以即使在最坏的情况下,你也会在每个分区中至少放置一个项目。唯一的例外是,如果您选择的三个项目都相同(在这种情况下,您通常需要/想要重新选择您的透视值(。
其次,像几乎所有使用迭代器的东西一样,std::partition
假设一个半开放范围——即,第一个迭代器指向范围的开头,第二个迭代器指向范围的末尾。这意味着您希望递归调用是:
quicksort(lowerIt, pIt);
quicksort(pIt, upperIt);
从理论上讲,跳过枢轴元素实际上不会造成任何伤害(并且可用于防止以前的问题(,但是在递归时将项目排除在处理之外是非常不寻常的,我通常会避免它。为了防止无限递归,您必须将枢轴交换到上部分区中的第一个位置,因此它是您在递归调用中传递的内容中遗漏的那个。如果你省略了一些其他元素,你会遇到问题,因为你不会对所有元素进行排序。
对于 Quicksort 的"严肃"实现,您可能还想更改其他一些细节,例如在分区大小减少到 20 个项目时停止递归,然后以这种方式完成时,对整个集合进行插入排序,以将所有内容放到其最终的休息位置(可以这么说(。
同样,为了避免堆栈溢出,您通常希望先对两个分区中较小的分区进行排序。这可确保堆栈空间永远不会超过 O(log N(。就目前而言,堆栈空间可能是O(N(最坏的情况。
- 为什么 std::unique 不调用 std::sort?
- 对字符串进行排序时,在c++中处理sort()
- std::sort()函数无法对向量的一部分进行排序
- 使用自定义比较函数使用std::sort()对矢量字符串进行排序时出现问题
- C++中"std::sort"比较器的不同类型
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- 按字母顺序对字符串中的字母进行排序,而无需使用内置的 sort()
- Softmax Implementation in C++
- c++无值sort()的问题是什么?
- 将用户定义的类型与 std::vector 和 std::sort 一起使用
- 使用 std::sort 对向量进行稳定排序
- 如何使用 QSortFilterProxyModel::sort 对 Qlist 中的数据进行排序
- std::sort 如何处理重复的数字?
- 为什么 std::sort 找不到合适的(静态成员)函数重载?
- C++ <algorithm> 使用对象作为比较定义的 sort()
- 尝试使用谓词函数会导致错误:"std::sort"未找到匹配的重载函数
- unqualified sort() -- 为什么它在 std::vector 上使用而不是在 std::array 上
- 使用 std::sort 对二维 c 数组进行排序
- std::stable_sort vs std::sort
- std::partition quick sort implementation