快速排序是我们比较常用的一种排序方式
详细代码如下:
/**
* Title: QuickSort.java
* File Description:
* @copyright: 2018
* @author: ranh
* @version: 2.0
* @date: 2018年10月24日
*/
package sort;
import java.util.Arrays;
import java.util.Random;
/**
* Class Description: 快速排序
* @author ranh
*/
public class QuickSort {
private static int order = 0;
public static void sort(int a[],int begin,int end){
order ++ ;
System.err.println("第" + order + "次循环数组下标:" + "x-"+begin +",y-"+ end);
int x = begin;
int y = end;
int basic = a[x];
while(x < y){
while (x < y && basic <= a[y]) {
y--;
}
if(x < y){
a[x++] = a[y];//不要被这里的x++所迷惑,其实只是a[x]=a[y],然后x++
a[y] = basic;//这里的赋值只是为了打印信息明朗
System.out.println("x>y 第" + order + "次:"+Arrays.toString(a) + " x:" + x + " y:" + y);
}
while (x < y && basic > a[x]) {
x++;
}
if(x < y){
a[y--] = a[x];//不要被这里的y--所迷惑,其实只是a[y]=a[x],然后y--
a[x] = basic;//这里的赋值只是为了打印信息明朗
System.out.println("x<y 第" + order + "次:"+Arrays.toString(a) + " x:" + x + " y:" + y);
}
// System.out.println("终 第" + order + "次:"+Arrays.toString(a) + " x:" + x + " y:" + y);
}
if( x-1 > 0 && x-1 > begin){//避免数组越界
sort(a, begin, x - 1);
}
if( x+1 < a.length && x + 1< end){//避免数组越界
sort(a, x + 1, end);
}
}
public static void main(String[] args) {
//生成长度为10的随机数组(从1~100)
int [] a = new int [10];
Random random = new Random();
for (int i = 0; i < 10; i++) {
a[i] = random.nextInt(100)+1;
}
System.out.println("初始数组:" + Arrays.toString(a));
sort(a,0,a.length-1);
System.out.println("排序数组:" + Arrays.toString(a));
}
}
运行结果如下
初始数组:[41, 60, 94, 42, 100, 80, 32, 17, 28, 16]
第1次循环数组下标:x-0,y-9
x>y 第1次:[16, 60, 94, 42, 100, 80, 32, 17, 28, 41] x:1 y:9
x<y 第1次:[16, 41, 94, 42, 100, 80, 32, 17, 28, 60] x:1 y:8
x>y 第1次:[16, 28, 94, 42, 100, 80, 32, 17, 41, 60] x:2 y:8
x<y 第1次:[16, 28, 41, 42, 100, 80, 32, 17, 94, 60] x:2 y:7
x>y 第1次:[16, 28, 17, 42, 100, 80, 32, 41, 94, 60] x:3 y:7
x<y 第1次:[16, 28, 17, 41, 100, 80, 32, 42, 94, 60] x:3 y:6
x>y 第1次:[16, 28, 17, 32, 100, 80, 41, 42, 94, 60] x:4 y:6
x<y 第1次:[16, 28, 17, 32, 41, 80, 100, 42, 94, 60] x:4 y:5
第2次循环数组下标:x-0,y-3
第3次循环数组下标:x-1,y-3
x>y 第3次:[16, 17, 28, 32, 41, 80, 100, 42, 94, 60] x:2 y:2
第4次循环数组下标:x-5,y-9
x>y 第4次:[16, 17, 28, 32, 41, 60, 100, 42, 94, 80] x:6 y:9
x<y 第4次:[16, 17, 28, 32, 41, 60, 80, 42, 94, 100] x:6 y:8
x>y 第4次:[16, 17, 28, 32, 41, 60, 42, 80, 94, 100] x:7 y:7
第5次循环数组下标:x-5,y-6
x>y 第5次:[16, 17, 28, 32, 41, 42, 60, 80, 94, 100] x:6 y:6
第6次循环数组下标:x-8,y-9
排序数组:[16, 17, 28, 32, 41, 42, 60, 80, 94, 100]
从中我们可惜清晰的了解到其运行机制。
在要排的数组(比如数组a)中选择一个中心值key(比如a[0]),通过一趟排序将数组a分成两部分,其中以key为中心,key右边都比key大,key左边的都key小,然后对这两部分分别重复这个过程,直到整个数组有序。
核心算法:
public static void sort(int a[],int begin,int end){
int x = begin;
int y = end;
int basic = a[x];
while(x < y){
while (x < y && basic <= a[y]) {
y--;
}
if(x < y){
a[x++] = a[y];
}
while (x < y && basic > a[x]) {
x++;
}
if(x < y){
a[y--] = a[x];
}
}
a[x] = basic;
if( x-1 > 0 && x-1 > begin){
sort(a, begin, x - 1);
}
if( x+1 < a.length && x + 1< end){
sort(a, x + 1, end);
}
}
时间复杂度:
- 最好:每次区间划分的结果都是基准关键字的左右两边长度相等或者相差为1,即选择的基准关键字为待排序的记录的中间值。此时进行比较次数总共为 nlogn,所以最好情况下快速排序的时间复杂度为O(nlogn)。
- 最坏:每次区间划分的结果都是基准关键字的左边(或右边)序列为空,而另一边区间中的记录仅比排序前少了一项,即选择的关键字是待排序记录的最小值或最大值。最坏情况下快速排序的时间复杂度为O(
)。
- 平均:平均时间复杂度为nlogn,且在所有平均时间复杂度为O(nlogn)的算法中,快速排序的平均性能是最好的。
空间复杂度:
- 最好:递归树的深度为
,其空间复杂度为O(nlogn)。
- 最坏:进行 n-1次递归,其空间复杂度为O(n)。
- 平均:空间复杂度为O(nlogn)。