我努力自己解决这个问题,但这让我更加困惑。我查看那些使用中位数对其进行分区的快速排序的示例代码,我在一个样本数组上尝试了它,说A = {1,8,4,6,7,10,11},我没有得到正确的分区。分区代码如下:
void swap(int &x, int &y){
int temp=x;
x=y;
y=temp;
}
//
int partition(int arr[],int low,int high){
int pivot=arr[(low+high)/2];
while(low<=high){
while(arr[low]<pivot) low++;
while(arr[high]>pivot) high--;
if(low<=high){
swap(arr[low],arr[high]);
low++;
high--;
}
}
return low;
}
对于我的示例,pivot是6,因此代码首先在数组A中交换8和6,然后停止。它之前没有放置比pivot = 6更小的值和上面的大值。我想问题是我们假设我们总能从枢轴的左侧和右侧找到两个值来交换,但是这个例子右侧是好的。任何意见或想法将不胜感激 只有少数更新:(1)我的重点是快速排序的分区部分,我知道以下步骤做一个递归方法。(2)我在很多链接中看到这个方法,即使在这个网站 Quick Sort - Middle Pivot implementation strange behaviour (或者在“破解编码访谈”一书中,第119页用java编写)并且他们声称它有效但我对此表示怀疑(我的意思是分区部分,它可能因某种原因以某种方式最终得到一个排序数组但是正确的必须实现分区,使得所有小于分区元素的数字都位于所有大于它的元素之前。)在我的样本数组A中,它最终得到A = {1,6,4,8,7,10,11这不是一个正确的分区,因为4是在6之后(我们的支点)。
答案 0 :(得分:0)
您的分区实施中存在一些明显的错误。其中一个较大的问题是,您不会重新比较swap
中的元素。
在Quicksort中进行分区时,只需要在pivot元素之后移动大于pivot的元素。所以,一个简单的实现就是......
int partition(int arr[], int begin, int end) {
int pivot = arr[begin + ((end - begin) / 2)];
while (begin != end) {
if (arr[begin] < pivot)
begin++;
else
swap(arr[begin], arr[end--]);
}
return end;
}
注意,复杂性取决于枢轴的质量,这就是为什么中位数是理想的。但是,这需要迭代所有元素O(n)
。
请记住,挑选数组的中间部分并不总能提供良好的支点。有一些策略可以选择一个好的支点(随机化,样本和中位数等等)。