快速排序的学习中遇到的问题(java)

来源:互联网 发布:阿里云免费6个月 编辑:程序博客网 时间:2024/05/16 04:31
package com.mmrx.quicksort;
/*快速排序*/
public class QuickSort {
/*主排序方法*/
public static void quickSort( int[] list ){
quickSort( list,0,list.length-1 );
}
/*辅助方法*/
private static void quickSort( int[] list,int first,int last ){
/*递归终止条件*/
if( last > first){
int pivotIndex = partition(list,first,last);
/*递归*/
quickSort( list,first,pivotIndex-1 );
quickSort( list,pivotIndex+1,last );
}
}
/*合并、寻找主元*/
private static int partition( int[] list,int first,int last ){
int pivot = list[first];
int high = last;
int low = first;
/*前后端遍历区间,找到前段大于主元,后端小于
* 主元的元素,交换位置*/
while( high > low ){
//
//while( high >low && list[low] <= pivot )
//low++;
//
//list[high] = list[low];//将比主元大的记录移动到高端
while( high >low && list[high] >= pivot )
high--;
list[low] = list[high]; //将比主元小的记录移动到低端
while( high >low && list[low] <= pivot )
low++;
list[high] = list[low];//将比主元大的记录移动到高端
}
list[low] = pivot;
return low;
}
}
问题1:在定位主元的方法partition中,两个while的顺序是否可以变?
/*前后端遍历区间,找到前段大于主元,后端小于
* 主元的元素,交换位置*/
while( high > low ){
//
//while( high >low && list[low] <= pivot )
//low++;
//
//list[high] = list[low];//将比主元大的记录移动到高端
while( high >low && list[high] >= pivot )
high--;
list[low] = list[high]; //将比主元小的记录移动到低端
while( high >low && list[low] <= pivot )
low++;
list[high] = list[low];//将比主元大的记录移动到高端
}
    由于在方法开头,我们将主元确定为序列第一个元素,之后的操作都是在序列本身上的赋值操作。
    在方法中保留的是主元的值,所以应该先将比主元小的记录移动到低端,再考虑比主元大的记录,即先考虑high,后考虑low。
    由代码可知,在high向前寻找的过程中,一旦发现元素值比pivot值小,就会将list[low]赋值为list[high]元素值,这样的话,list[low]原本的值就会丢失。但是最开始的list[low]已经被作为主元保留了下来,所以没有影响。
    如果代码是这样
while( high > low ){
while( high >low && list[low] <= pivot )
low++;
list[high] = list[low];//将比主元大的记录移动到高端
while( high >low && list[high] >= pivot )
high--;
list[low] = list[high]; //将比主元小的记录移动到低端
//while( high >low && list[low] <= pivot )
//low++;
//
//list[high] = list[low];//将比主元大的记录移动到高端
}
    首先进行的是low向后遍历数组,找到的low索引值应该是比主元大的数组元素的索引,此时,list[high]原本的值被list[low]值覆盖,彻底丢失,就会使得数组内容被改变,结果自然也就不正确了。

问题2:
list[low] = pivot;
return low;
返回值为何是low而不是high?
    有这么几种情况,第一种,在while中不发生值交换,那么主元的位置仍旧是原本的位置,即low(数组索引为0的位置);第二种,在while中发生值交换,执行完毕下面一句后不再发生值交换,结束循环。
list[low] = list[high]; //将比主元小的记录移动到低端
即low值被覆盖,此时list[low] == list[high],比主元小的值被向前移动了,但是high位置的元素空下了,而high位置的值应当为pivot,low向后挪动,high不变,执行完毕循环,有low == high,接下来执行问题2中的语句也就顺理成章了;第三种,执行完毕下面后不再发生值交换,结束循环,
list[high] = list[low];//将比主元大的记录移动到高端

从high位置开始向前遍历,找到比主元小的元素,执行 list[high] = list[low],比主元大的值被向后移动,low位置的元素空下了,high向前挪动,low的值不变,执行完毕循环,有low == high,执行问题2中的语句。

    实质上,只有两种可能,不发生值交换(low == 0)和发生值交换(最终肯定有low == high),而第一种可能就决定了返回值只能是low而不是high。

0 0
原创粉丝点击