基本思想:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
public class QuickSort {
public static void main(String[] args) {
int[] arr = {9,8,7,6,5,4,3,2,1};
quickSort(arr,0,arr.length-1);
}
public static void quickSort(int arr[],int l,int r){
if (l < r) {
//调整当前数组并返回分割点位置
int m = adjust(arr, l, r);
//递归调整分割点左边数组
quickSort(arr, l, m-1);
//递归调整分割点右边数组
quickSort(arr, m + 1, r);
}
}
//以首位数字为基数,将比基数小数字放在基数左边,比基数大的数放在基数右边
//注意,此算法是利用在同一个数组上做调整,未另开辟空间
public static int adjust(int arr[],int l,int r){
int i = l;
int j = r;
int base = arr[i];
while (i < j){
//从右往左找比基准点小的数,找到交换位置,找不到往左走一步继续找
while (i < j && arr[j] >= base){
j--;
}
//交换
arr[i] = arr[j];
//从左往右找比基准点大的数,找到交换位置,找不到往右走一步继续找
while (i < j && arr[i] <= base){
i++;
}
arr[j] = arr[i];
}
//i为基准点的目标位置
arr[i] = base;
return i;
}
}
另一种:
//快速排序
public static void quickSort(int arr[],int l,int r){
if(l>r)
return;
int base = arr[l];
int i = l;
int j = r;
while (i < j){
//从右往左查找第一个比base大的元素
while (arr[j] >= base && i < j){
j--;
}
//从左往右查找第一个比base小的元素
while (arr[i] <= base && i < j){
i++;
}
//将找到的比base大的和比base小的两元素交换
if (i < j){//为什么if判断?i和j可能相等,就没必要交换了
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
//将基数与i、j碰撞位置的数交换。此次排序达到了i位置左边元素都比base小,右边都比base大
arr[l] = arr[i];
arr[i] = base;
//递归快速排序左、右
quickSort(arr,l,i-1);
quickSort(arr,i+1,r);
}
最优时间复杂度:O(n*logn),最坏时间复杂度O(n2)
最优空间复杂度都为:O(logn),最坏空间复杂度O(n)。空间复杂度主要是由递归造成的栈空间使用。
由于关键字的比较与交换是跳跃进行的,因此,快速排序是一种不稳定的排序方式。
参考: