快速排序
快速排序的基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录,继续进行排序,已达到整个序列有序。
白话解释:
1. 先从数列中取出一个数做基准,这个位置叫枢轴
2. 分区过程,将比这个数大的放在右边,小于或者等于的放在左边
3. 在对左右区间重复第2步直到,区间只有一个数据
排序方法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 |
---|---|---|---|---|---|
快速排序 | O( nlogn ) | O( nlogn ) | O( n2 ) | O( logn )-O( n ) | 不稳定 |
快速排序是几个O(
代码实现:
public static int[] quickSort(int[] A,int length){
if(A==null || length<=0){
throw new IllegalArgumentException("the input is error");
}
Quick(A,0,length-1);
return A;
}
public int[] Quick(int[] A,int left,int right){
if(left<right){
int middle = Partition(A,left,right);
Quick(A,left,middle-1);
Quick(A,middle+1,right);
}
return A;
}
public int Partition(int[] A,int left,int right){
int key=A[left];
while(left<right){
while(left < right && A[right]>=key){
right--;
}
A[left]=A[right];
while(left < right && A[left]<=key){
left++;
}
A[right]=A[left];
}
A[left]=key;
return left;
}
partition函数的作用就是先选取一个关键字,然后想尽一切办法,将它放到一个位置,使它左边的值都比它小,右边的值比它大,这样的关键字称为枢轴。
例子:{50,10,90,30,70,40,80,60,20}
key = A[left] = 50
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
50 | 10 | 90 | 30 | 70 | 40 | 80 | 60 | 20 |
left | right |
20不符合,赋值给50
执行partition
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
20 | 10 | 90 | 30 | 70 | 40 | 80 | 60 | 20 |
left | right |
90不符合,赋值给8号位
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
20 | 10 | 90 | 30 | 70 | 40 | 80 | 60 | 90 |
left | right |
40不符合,赋值给2号位
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
20 | 10 | 40 | 30 | 70 | 40 | 80 | 60 | 90 |
left | right |
70不符合,赋值给5号位
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
20 | 10 | 40 | 30 | 70 | 70 | 80 | 60 | 90 |
left right |
left和right指向同一位置,将A[left] = key
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
20 | 10 | 40 | 30 | 50 | 70 | 80 | 60 | 90 |
left right |
一次partiton过程结束,返回key的位置,继续递归调用quick。
优化方法:
优化选取的枢轴,我们代码中选的是left,可以优选成三数取中法,三个关键字进行排序,将中间的选为枢轴,一般取左端、右端和中间三个数。