我一直在尝试实现Hoare分区方法,但是我和计算机似乎都无法理解它,因为它是用Cormen和Wikipedia编写的。 两个来源中的算法如下所示:
algorithm partition(A, lo, hi) is
pivot := A[lo]
i := lo - 1
j := hi + 1
loop forever
do
j := j - 1
while A[j] > pivot
do
i := i + 1
while A[i] < pivot
if i < j then
swap A[i] with A[j]
else
return j
对于以下数组:9 3 11 55 4,在使用上述函数对其进行分区后,它将如下所示:4 3 11 55 9并且数据透视索引将为2,这是完全错误的。首先,9和4将被交换,所以我将变为2,j将变为4.但是,在下一次迭代中,由于do while循环,将跳过9并且永远不会再次交换。 我的想法有问题吗? (我认为我在C ++中的实现没有任何错误)
#include <iostream>
using namespace std;
int a[100];
int partitie(int st, int dr){
int i,j,x;
x=a[st];
i=st-1;
j=dr+1;
while(true){
do{
j--;
}while(a[j]>x);
do{
i++;
}while(a[i]<x);
if(i<j) swap(a[i],a[j]);
else return j;
}
}
int main() {
int i,n;
cin>>n;
for(i=1;i<=n;i++) cin>>a[i];
cout<<partitie(1,n)<<endl;
for(i=1;i<=n;i++) cout<<a[i]<<" ";
return 0;
}
答案 0 :(得分:1)
你需要使用正确的快速排序例程,因为Hoare将一个数组拆分为左侧部分和右侧部分,不像Lomuto将数组分成左侧部分,枢轴,右侧部分。
algorithm quicksort(A, lo, hi) is
if lo < hi then
p := partition(A, lo, hi)
quicksort(A, lo, p) // not quicksort(A, lo, p-1)
quicksort(A, p + 1, hi)
在中间选择一个数据透视表示已经排序或反向排序的数组快速排序,而不是最坏的情况:
pivot := A[lo+(hi-lo)/2] // or := A[(lo+hi)/2] if overflow not an issue
仍然会出现最糟糕的案例模式,但至少会处理简单的案例。 3的中位数有点慢,但减少了最坏情况模式的数量:
md = lo + (hi-lo)/2
if (A[lo] > A[hi])
swap(A[lo], A[hi])
if (A[lo] > A[md])
swap(A[lo], A[md])
if (A[md] > A[hi])
swap(A[md], A[hi])
pivot := a[md]
也许您正在寻找的是快速选择找到第k个元素,其中k =数组大小/ 2.它类似于快速排序,但它只是递归搜索左侧或右侧部分包含第k个元素的数组。维基文章: