原理:
就是选一个数作为基准数(一般是左边或者右边第一个数),从右边开始(跟基准数选的方向相反),找到比基准数大的第一个数替换到基准数的位置(这时候基准数已经被记录了,所以不会丢失),同时左标记点+1,从左边开始找到第一个比基准数大的数(这是为了保证左边的数都是比基准数小),将这个数赋值到右标记点的位置,直到i>=j,这时候表示大小都分布在右左两侧,这时候将基准数赋值到左标记点现在的位置,这样左边的数都比基准数小,右边的数都大。然后再次递归左边的数快排,右边的数快排。直到递归到里面的数不满足l<r。这个时候就是排序完成(也就是说就剩一个数,l==r,一个数也就代表它是有序的)。
图示:
这个动图的基准数设的是右边,所以他是从左边开始查找,比基准数大的数,然后放在右边(可能跟我的方法不太照应,但是没有更好的图,大家还是以看代码为主,我的思想都写在注释上了)
代码实现:
public class QuickSort {
public void quickSort(int[] arr,int l,int r){
//首先判断是否有在正确的区间
if(l<r){
int i,j,x;
i=l;
j=r;
x= arr[i];//设置基点为最左边的数
while(i<j){//结束的时候,大数都排到右边啦,小数到左边啦
//arr[j]>=x,当右边的数=x时候,不进行置换
while (i<j&&arr[j]>=x)
j--;
if(i<j){//把小于基点的数尽量放在左边
arr[i++]=arr[j];
}
while (i<j&&arr[i]<=x)
i++;
//把大于x的数放在右边已经被使用过的数的位置
if(i<j){arr[j--]=arr[i];}
}
arr[i] = x;
quickSort(arr,l,i-1);
quickSort(arr,i+1,r);
}
}
public static void main(String[] args) {
int[] a = {80,35,210,40,20,0,50,29};
new QuickSort().quickSort(a,0,a.length-1);
System.out.println(Arrays.toString(a));
}
}
时间复杂度
快速排序的时间复杂度在最坏情况下是O(N2),平均的时间复杂度是O(N*lgN)。
这句话很好理解:假设被排序的数列中有N个数。遍历一次的时间复杂度是O(N),需要遍历多少次呢?至少lg(N+1)次,最多N次。
快速排序不是稳定算法。