我在某些地方读到,如果不选择第一个或最后一个元素作为枢轴,则应该在分区开始之前先将其与第一个或最后一个位置交换。因此,我尝试了一个示例,并使用此算法https://www.cs.auckland.ac.nz/software/AlgAnim/qsort1a.html 获得了正确的分区。
此分区方法使用左指针和右指针。它将左指针移向中心,直到找到比枢轴更大的元素。然后,它将右指针移向中心,直到找到小于枢轴的元素。如果rightpointer> leftpointer。这两个位置的值被交换。最后,将枢轴放置在右指针的位置。
对于输入阵列12、18、17、11、13、15、16、14,选择元素15作为枢轴。
这些步骤是:
12、18、17、11、13、15、16、14
12,14,17,11,11,13,15,16,18(交换18和14)
12,14,13,11,17,17,15,16,18(交换17和13)
12,14,13,11,15,15,17,16,18(交换15和17)
该霍尔分区方案是在概念上的问题的例子类似,不同的是初始枢转值可以从任何地方在阵列内作出,并且不执行特殊的端的情况下交换,当枢转值和枢轴指针将结束在Hoare分区期间处于正确位置。
这是一个快速排序的示例,该示例使用3的中位数,Hoare分区方案,排除与枢轴相邻且相等的元素(它们已经排序),并且仅对较小的分区使用递归将最坏情况的堆栈空间限制为O(log (n))。
void QuickSort(uint32_t a[], size_t lo, size_t hi) {
while(lo < hi){
size_t i = lo, j = (lo+hi)/2, k = hi;
uint32_t p;
if (a[k] < a[i]) // median of 3
std::swap(a[k], a[i]);
if (a[j] < a[i])
std::swap(a[j], a[i]);
if (a[k] < a[j])
std::swap(a[k], a[j]);
p = a[j];
i--; // Hoare partition
k++;
while (1) {
while (a[++i] < p);
while (a[--k] > p);
if (i >= k)
break;
std::swap(a[i], a[k]);
}
i = k++;
// at this point, a[i] or a[k] or both == p (pivot value)
while(i > lo && a[i] == p) // exclude middle values == pivot
i--;
while(k < hi && a[k] == p)
k++;
// recurse on smaller part, loop on larger part
if((i - lo) <= (hi - k)){
QuickSort(a, lo, i);
lo = k;
} else {
QuickSort(a, k, hi);
hi = i;
}
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句