思想
快速排序是对冒泡排序的一种改进,冒泡排序每次将未排序的数组中最大的一个数通过交换的方式放到正确的位置上,而快速排序是选取一个中轴元素,然后把数组中所有小于中轴元素的元素放在其左边,所有大于或等于中轴元素的元素放在其右边,显然,此时中轴元素所处的位置的是有序的。也就是说,我们无需再移动中轴元素的位置。
动图演示如下:
(动图取自微信公众号:帅地玩编程)
如何使中轴元素位于正确的位置
由于中轴元素左边的值都比它小,右边的值都比它大,所以采用双指针的方法同时维护两个数组,左边维护一个比它小的数组,右边维护一个比它大的数组。由于中轴元素已经取出来了,所以中轴元素一开始所在的位置(左指针初始值)可以用来放其他的元素,右边指针一直移动到一个比中轴元素小的位置,然后将它放到左边的指针所指的位置,然后将左边指针一直移动到一个比中轴元素大的位置,然后将它放到右边的指针所指的位置,最后把中轴元素放到此时指针的位置(此时两个指针的位置相等)
代码实现
public static void quicksort(int [] nums,int left,int right){
//如果left >= right时,说明此时递归的数组长度为1,就不需要操作了
if(left>=right)return;
//记录主元的值
int pivot = nums[left];
//这一步i的初始值很巧妙,由于主元的值已经记录过了,所以i下标所在的数组
//数组位置等于一个空的位置,可以用来放其他的数字
int i = left;
int j = right;
while(i<j){
//这里一定要先计算j,因为可以直接将j处的值放到i的空位置处
while (i < j && nums[j] >= pivot) {
j--;
}
if (i < j) {
nums[i] = nums[j];
i++;
}
//当把j处的值放到空位置处的时候,j处的位置又空了。
while (i < j && nums[i] <= pivot) {
i++;
}
if (i < j) {
nums[j] = nums[i];
j--;
}
}
//把主元放到正确的位置,i和j都可以
nums[i] = pivot;
//递归进行移动
quicksort(nums,left,i-1);
quicksort(nums,i+1,right);
}