一个quickSort递归方法,一个partition分治方法,一个swap交换方法,都是三个参数一样int[] arr ,int low,int high。
组名arr、最小索引low、最大索引high。。不过quickSort没有返回值,partition方法需要返回分界的索引值(两部分的中间索引)。
整个快速排序算法的实现主要由quickSort递归方法和partition分治方法组成;其中quickSort递归方法是固定的,而partition分治方法主要有两种实现。
- quickSort递归方法
对于递归quickSort方法都是一致的:
public void quickSort(int[] array,int low,int high){
if(low >= high) return;//递归终止条件
int mid = partition(array,low,high);
quickSort(array,low,mid-1);//递归前一半
quickSort(array,mid+1,high);//递归后一半
}
- partition分治方法
利用while只需要赋值就可以完成,不需要执行交换,因为让arr[high]或arr[low]作pivot,这样high或low位置就可以认为空出来了。
while实现原理:从两端开始遍历,具体从哪一端开始根据pivot为arr[high]还是arr[low]有关。若pivot=arr[high],则从左端开始,反之从右端开始。原因:左端遍历目的是找出大于pivot的元素,需要调到右端,因此需要空位置在右端。
无论从左向右还是从右向左,原理是一样的。以从左向右为例,利用while循环直到找到大于pivot的元素为止,然后将该元素赋值于空位置,同时该位置就变为空位置。从右向左同理,这样一直循环下去。直到i>=j。最后将pivot赋值于空位置即可。
- 利用while实现
原理:
纯代码:
public int partition(int[] arr,int low,int high) {
int pivot = arr[high];
int i = low,j = high;
while(i < j) {
while(i < j && pivot >= arr[i]) i++;
if(i < j) arr[j--] = arr[i];
while(i < j && pivot <= arr[j]) j--;
if(i < j) arr[i++] = arr[j];
}
arr[j] = pivot;
return j;
}
解释版本:
public int partition(int[] arr,int low,int high) {
//令末尾值为基准值;这样末尾值就保存到pivot中,可以认为high为空
int pivot = arr[high];
int i = low,j = high;
while(i < j) {
//pivot = arr[high]==>必须先从高到低遍历
//pivot = arr[low]==>必须先从低到高遍历
while(i < j && pivot >= arr[i]) i++;//从高到低:直到找到一个小于pivot的元素
if(i < j) arr[j--] = arr[i];//将找到的小于pivot的元素赋值于空位置并j减1;arr[i]可以认为为空
while(i < j && pivot <= arr[j]) j--;//从低到高:直到找到一个大于pivot的元素
if(i < j) arr[i++] = arr[j];//将找到的大于pivot的元素赋值于空位置并i+1;arr[j]可以认为为空
}
arr[j] = pivot;//将pivot至于arr[j]空位置
return j;
}
若利用arr[low]作pivot,则
public int partition4(int[] arr,int low,int high) {
int pivot = arr[low];
int i = low, j = high;
while(i < j) {
while(i < j && pivot <= arr[j]) j--;
if(i < j) arr[i++] = arr[j];
while(i < j && pivot >= arr[i]) i++;
if(i < j) arr[j--] = arr[i];
}
arr[i] = pivot;
return i;
}
- 利用for循环实现
原理:以arr[high]作为基准值,用j作为遍历索引low—high-1,用i作为小于pivot的索引,从0开始,保证索引i之前的都是小于pivot;遍历过程中,如果arr[j]小于基准值,就将arr[j]与++i值互换位置,如果大于等于基准值,则i不增加,也不交换,继续遍历。
说白了:就是把小于基准值的数往前调,把大于基准值的数往后赶。
如果令arr[high]作pivot,则
private int partition(int[] array,int low,int high){
int pivot = array[high];//随意指定,一般另high处为基准
int i = low;
for(int j = low;j < high;j++){//由于pivot为high值,因此不遍历high
if(array[j] < pivot){
swap(array,i++,j);
}
}
swap(array,i,high);
return i;
}
如果令arr[low]作pivot,则
public int partition(int[] arr,int low,int high) {
int pivot = arr[low];
int i = high;
for(int j = high;j > low;j--) {
if(arr[j] >= pivot) {
swap(arr,j,i--);
}
}
swap(arr,i,low);
return i;
}
for循环需要利用swap方法:交换数组中两个位置的值
private void swap(int[] array,int i,int j){
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}