一、基本思想
快排是对冒泡排序的一种改进,基本思想是:通过一趟排序将数组分成左右两部分,使得左边的所有数都比右边的所有数小,然后再对左右两部分分别进行快速排序,可以递归进行,使得整个数组有序排列。
向左递归:直至R指针>=left,则左递归结束;
向右递归:直至L指针<=right, 则右递归结束;
快速排序逻辑图
二、代码实现
package sort;
import java.util.Arrays;
/**
* 快速排序
* 思路分析:
* (1)首先找一个中轴数,以这个数为轴将一组数分成两部分,从左右两边开始向中间遍历,从左边找一个比中轴数大的,从右边找一个比中轴数小的,然后让这两个数交换
* 然后左右两边的指针向中间移动,直至一轮遍历结束,比中轴数小的都放在它左边,比中轴数大的都放在它右边。
* (2)一轮遍历结束后,中轴数左侧都是比它小的,但不一定有序。右侧都是比它大的,但不一定有序。因此再分别对中轴数左右两侧的数按照(1)中的逻辑继续进行排序。
* (3)直至所有数有序排列为止。
*/
public class QuickSort {
public static void main(String[] args) {
int[] arr = {-9,78,0,23,-567,70};
System.out.println(Arrays.toString(arr));
quickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int[] arr,int left,int right){
int l = left;//最左侧指针,用于向右移动寻找比中轴数大的数。
int r = right;//最右侧指针,用于向左移动寻找比中轴数小的数。
int pivot = arr[(left+right)/2];
int temp =0; //临时变量,交换数据时使用
while (l<r){
//在pivot的左侧一直找,直到找到一个大于等于pivot的数,则停下来
while (arr[l]<pivot){
l++;
}
//在pivot的右侧一直找,直到找到一个小于等于pivot的数,则停下来
while (arr[r]>pivot){
r--;
}
//因为上面循环条件是arr[l]<pivot,arr[r]>pivot,即:最极端的情况是左侧和右侧都刚好找到了pivot处,即 l==r,
// 此时pivot的左侧已经都是比它小的,右侧都是比它大的了。
if(l >= r){
break;
}
temp = arr[r];
arr[r] = arr[l];
arr[l] = temp;
//如果交换完后发现l所指的数等于pivot,则r--,因为有可能只是一个和pivot的值相等的一个数,需要从右测继续找一个。
if(arr[l]==pivot){
r--;
}
//如果交换完后发现r所指的数等于pivot,则l++,因为有可能只是一个和pivot的值相等的一个数,前面还有需要比较的。
if(arr[r]==pivot){
l++;
}
}
//一轮循环结束,为左右两侧递归作准备
if(l==r){
r--;
l++;
}
//向左递归,左递归可以继续进行的条件是 left < r ,否则结束
if(left<r){
quickSort(arr,left,r);
}
//向右递归,右递归可以继续进行的条件是 l<right ,否则结束
if(l<right){
quickSort(arr,l,right);
}
}
}
三、性能对比
以80000个数据测试,耗时大约30ms