首先我们简单看下一个快速排序代码:
//假设需要排序的数组为 3,7,4,5,8,2,6
public static void quickSort(int[] array,int low,int high)
{
int i=low; int j=high;
if(i<j){
int temp=array[i];
while(i<j){
if(i<j&&array[j]>=temp){ j--; }//这从右边开始 j--
array[i]=array[j];
if(i<j&&array[i]<=temp){ i++; }
array[j]=array[i];
}
array[i]=temp;
quickSort(array,low,i-1);
quickSort(array,i+1,high);
}
}
快速排序的原理不再讲解,网上很多,我们就来看看在while循环中,为什么要从右边开始?
总结来说就一句话:因为我们的基准数在左边,如果从左边开始那么会丢失数据,并且不能正确排序
假如从左边开始是什么情况,伪代码如下
while(i<j){
if(i<j&&a[i]<=temp){ i++; }//从左边开始
a[j]=a[i];
if(i<j&&a[j]>=temp){ j--; }
a[i]=a[j];
}
假设数组为:【3,7,4,5,8,2,6】
基准数为3,当i=1的时候,即a【i】=7的时候,比基准数大,结束i++循环,这个时候j=a.length-1 即为6,执行a【j】=a【i】,结果就是
【3,7,4,5,8,2,7】;
接着进入j--的if判断,到了j=5的时候,即a【j】=2,结束j--的循环,这个时候i=1,执行a【i】=a【j】,执行完毕后的结果是
【3,2 ,4,5,8,2,7】;
细心的人这个时候就应该发现问题了,少了一个数 6 ,并且数组出现问题(两个2),后面的不再叙述,有兴趣的小伙伴们可以接着走一下,问题更明显
正确的快速排序是基准数在左边,从右边开始,按照上面的逻辑走下去,我们也会少一个数,少的这个数就是基准数,但是这个基准数已经赋值给了temp,最后会把这个temp赋值给a【i】(每次while循环完会有个赋值操作array[i]=temp;),所以最后也不会少数据。
这个时候或许就有小伙伴们问了,那么把基准数设置在右边,从左边开始可以得到正确结果吗?
答案是 可以的
根据上面的分析,自己走走流程发现可以得到正确答案,为了验证我也写了基准数设置到右边,从左边开始的代码,测试是通过的。
public static void quickSort2(int[] array,int low,int high){
int i=low; int j=high;
if(i<j){
int temp=array[j];
while(i<j){
if(i<j&&array[i]<temp){ i++; }
array[j]=array[i];
if(i<j&&array[j]>temp){ j--; }
array[i]=array[j];
}
array[i]=temp;
quickSort2(array,low,i-1);
quickSort2(array,i+1, high);
}
}