快速排序的基本实现(Java)
快速排序的关键步骤是将基准数归位。
举个例子,假定有一个数组:int[] arr = {4,5,1,2,6,8,9,3,7}
,并且我们要把他按从小到大排序。
选定第一个元素4作为基准数,归位的意思是要把它放到应该放的位置上去,同时左边的数都小于基准数,右边的数都大于基准数。
可以设两个变量,我给他们取名为leftWalker和rightWalker。首先rightWalker从右到左找一个比基准数小的数,然后leftWalker从左到右找一个比基准数大的数,将他们所指的值交换;当两个walker撞到一起时,就把基准数和两个walker所指的数进行交换,此时基准数归位完毕。
我们可以将基准数归位的操作封装为一个函数restoreFIrst(int[] array)。当前数组进行一次基准数归位后,后面要做的就是对基准数左边的元素组成的数组和基准数右边的元素组成的数组分别进行基准数归位,这里应用了递归解决问题的思想,例如:
arr1 arr2 arr3 arr4 arr5 **index** arr6 arr7 arr8 arr9
下面要做的是restoreFirst({arr1,arr2,arr3,arr4,arr5})
和restoreFirst({arr6,arr7,arr8,arr9})
很重要的问题,递归的出口是当前array的长度小于1时,直接return。
当所有子序列处理完毕后,快速排序也就结束了,这时可以输出排序后的结果。
附完整代码:
package com.adam.sort;
import java.util.Arrays;
/**
* @author adam
* 创建于 2018-03-05 22:27.
* 快速排序(从小到大)。
*/
public class QuickSort {
public static void main(String[] args) {
int[] array = {6,8,4,3,5,2,9,1,7,19,-2};
quicksort(array,0,array.length-1);
System.out.println(Arrays.toString(array));
}
private static void quicksort(int[] array,int startIndex, int endIndex) {
int index = restoreFirst(array,startIndex,endIndex);
if(index==-1){
return;
} else {
quicksort(array,startIndex,index);
quicksort(array,index+1,endIndex);
}
}
//返回值:归位后基准数index
private static int restoreFirst(int[] array,int startIndex,int endIndex) {
if(endIndex-startIndex <= 0){
return -1;
} else {
int first = array[startIndex]; //基准数
int leftWalker = startIndex, rightWalker = endIndex; //左右哨兵
while(true) {
//从右面找一个比first小的数
while(array[rightWalker] >= first && rightWalker > leftWalker)
rightWalker--;
//从左面找一个比first大的数
while(array[leftWalker] <= first && leftWalker < rightWalker)
leftWalker++;
//当左右哨兵不等时,交换这两个哨兵指向的值
if(leftWalker != rightWalker) {
int temp = array[leftWalker];
array[leftWalker] = array[rightWalker];
array[rightWalker] = temp;
} else { //否则将哨兵所指的值与基准数交换
array[startIndex] = array[leftWalker];
array[leftWalker] = first;
return leftWalker;
}
}
//跳出循环时,基准数已归位
}
}
}
运行结果:
[-2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 19]
2019/06/01
附第二种实现方式:
public class QuickSortMain {
public static void main(String[] args) {
int[] arr = {90,45,200,1,48,8899,23};
sort(arr, 0, arr.length-1);
System.out.println(Arrays.toString(arr));
}
private static void sort(int[] arr, int left, int right) {
if(left >= right) return;
int base = arr[left];
int lw = left, rw=right;
while(lw!=rw) {
//注意:此处必须先从右边找。因为基准数选的是左边第一个。
while (lw < rw && arr[rw] >= base) rw--;
while (lw < rw && arr[lw] <= base) lw++;
if (lw != rw) {
int tmp = arr[lw];
arr[lw] = arr[rw];
arr[rw] = tmp;
}
}
if(lw!=left) {
arr[left] = arr[lw];
arr[lw] = base;
}
sort(arr, left, lw-1);
sort(arr, lw+1, right);
}
}