在某些情况下,我的快速排序实现失败
Posted
技术标签:
【中文标题】在某些情况下,我的快速排序实现失败【英文标题】:My quick sort implementation fails in some cases 【发布时间】:2012-12-09 18:31:33 【问题描述】:我已经实现了一个快速排序算法,但是当我对其进行测试时,我注意到当输入数组在第一个元素中具有最大元素时它会失败(这是我从中获得枢轴的元素)。这是我的代码:
void partition(int *a,int size)
if(size<=1)return;
int pivot=a[0];
int left=0,right=0;
for(left=1,right=size-1;left<=right;) //was size-1
if(a[left]>=pivot&&a[right]<=pivot)
swap(left,right,a);
if(a[left]<pivot)left++;
if(a[right]>pivot)right--;
swap(0,right,a);
partition(a,right-1);
partition(&(a[right+1]),size-right-1);
一些失败的样本:
I/P 245 111 32 4
O/P 4 111 32 245 `
I/P 154 11 43 3 7
O/P 7 11 43 3 154
我可能犯了哪些错误?
【问题讨论】:
与上一个问题Quick sort partition algorithm密切相关。 【参考方案1】:好吧,问题出在这里:
partition(a,right-1); // <- It's partition(array,size)!
改成
partition(a,right);
它会起作用的。我想你知道原因。 要使分区功能正常工作,您必须提供两件事:
1) 要处理的数组。 2) 它拥有的元素数量,大小。
问题在于第一次递归调用分割左子数组:partition(a,right-1)
参数 2,size
,被错误地指定为right-1
,而实际上它是right
。
这可以通过使用数组中从索引a
到b
(包括b>=a
)的元素数量为N= b-a+1
这一事实来解决。
在这里,我们有a=0
、b=right-1
,因此是左子数组中的元素数,即size
、N
=(right-1)-(0)+1
=right
。
因此要正常工作,您必须像 partition(a,right);
一样调用它。
左子数组以right-1
结尾,但它有right-1+1
=right
元素。
一直在发生:)
【讨论】:
请您提供更多解释吗? 你的意思是我必须通过 right 而不是 right-1 因为我从元素 1 开始? @Eslam 已更新。阿米特的观点也值得注意。希望这会有所帮助。【参考方案2】:您错过了在分区函数中数组中有一个元素是枢轴的情况。
假设arr = 5, 5, 1 , 1, 5,
pivot = 5
iter1:
left=1, arr[left]=5 ; right=4,arr[right]=5
(swapping)
not increasing left nor decreasing right - since 5 < 5 == false ; 5 > 5 == false
下一次迭代,同样的场景会重演,你实际上会得到一个无限循环。
处理它的一种方法是确定“大”部分也将增加所有恰好是枢轴的元素,如果arr[right] < pivot
(不是<=
)交换元素,如果@则减少right
987654326@(不是>
),类似于:
...
for(left=1,right=size-1;left<=right;) //was size-1
if(a[left]>=pivot&&a[right]<pivot)
// ^ note < not <=
swap(left,right,a);
if(a[left]<pivot)left++;
if(a[right]>=pivot)right--;
// ^ note >=
...
【讨论】:
好的,这是一个很好的通知,但这不是上述问题的主要原因,谢谢以上是关于在某些情况下,我的快速排序实现失败的主要内容,如果未能解决你的问题,请参考以下文章