快排的基本思想:
选定一个基准值,把所有小于基准值的元素移动到基准值前面,大于基准值的元素移动到基准值后面。我们把这个过程称为“分区”, 分区完成后,基准值在数组的位置就不需要改变了,对分好的两个区域继续进行“分区”,直到分区大小为1。
图片来自维基百科
1、对待排序的数组进行划分
下面举例说明划分的流程:
1.1、 首先把数组第0个元素前面的位置(-1)作为“小于区域”,数组最后一个元素作为划分的基准值(暂时让这个基准值位于“大于区域”
1.2、从0开始遍历数组,当前值如果小于基准值,则“小于区域”+ 1, 如果大于基准值,则当前值与“大于区域”的前一个元素交换,“大于区域+ 1”,如果等于基准值则什么都不做,下标加1,如此重复,直至下标与“大于区域”的边界相遇。
1.3 把数组最后一个元素与大于区域的第1个元素交换,便可以得到划分好的三个区域(小于、等于、大于)
1.4返回等于区域的左右边界
2、对划分好的“小于区域”与“大于区域”继续执行划分,直至不能再划分,则数组顺序排好了。
package com.yuan.sort;
public class QuickSort {
public static void main(String[] args) {
int[] test;
int maxSize = 20;
int maxValue = 50;
test = generateRandomArray(maxSize, maxValue);
printArray(test);
quickSort(test);
printArray(test);
}
private static void quickSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
quickSort(arr, 0, arr.length - 1);
}
private static void quickSort(int[] arr, int left, int right) {
if (left < right) {
swap(arr, left + (int)(Math.random() * (right - left + 1)), right); //随机快排
int[] p = partition(arr, left, right);
quickSort(arr, left, p[0] - 1);
quickSort(arr, p[1] + 1, right);
}
}
private static int[] partition(int[] arr, int left, int right) {
int less = left - 1;
int more = right;
while (left < more) {
if (arr[left] < arr[right])
swap(arr, ++less, left++);
else if (arr[left] > arr[right])
swap(arr, --more, left);
else
left++;
}
swap(arr, left, right);
return new int[]{less + 1, more}; //返回等于区域的左右边界。
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
private static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[maxSize];//[(int)((maxSize + 1) * Math.random())];
for (int i = 0; i < maxSize; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
private static void printArray(int[] arr) {
for (int prime : arr) {
System.out.print(prime + " ");
}
System.out.println();
}
}
测试结果
input: 18 -13 -35 13 -9 -27 16 11 -20 11
output: -35 -27 -20 -13 -9 11 11 13 16 18
算法复杂度
1、当每次划分的区域大小相当的时候,得到最好时间复杂度
O(n⋅logn)
O
(
n
⋅
l
o
g
n
)
2、当每次划分的区域大小为1与n-1时,得到最坏时间复杂度
O(n2)
O
(
n
2
)