快速排序

这里写了个快速排序的工具类,简单写一下它的工作方式吧。

有数组[4,3,5,2]如图,
1.取第一个元素赋给临时变量v,循环结束时,v左边的都小于v,v右边的都大于v;
2.以v为中心划分,得到两个小数组,递归1;

快速排序虽然使用了递归,但是由于是log(n),所以栈的深度并不高,就算是Integer.MAX_VALUE的数组,栈顶多31层。
它是最常用的排序算法了吧应该,有人说堆排序和快速排序都是O(nlogn),堆没有递归,所以堆排序比快速排序更好。有没有递归并不能决定一个算法的好坏,其实好与不好要看使用场景的,如果仅仅是对一个数组排一下序,选快速排序;如果要一直维护一个有序队列,选堆排序。
快速排序的理想时间复杂度是O(nlogn),为什么说是理想呢,因为如果待排序的数组正好是倒序的,快速排序的分治策略就很差了,它总是把左右数组分为大小为n-1和0两个,所以递归的深度一下子变成了n,如果数组长度为1000000,直接就栈溢出了,并且时间复杂度成了O(n^2)。所以快排也是不稳定的排序算法,为了防止这样的情况发生,通常是随机取个比较基准,而不是每次都取首元素,我觉得每次都取中间的也是不错的选择。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package structure;

import java.util.Arrays;

/**
* @author hero
*/
public abstract class QuickSort {

public static void sort(Object[] array) {
sort(array, 0, array.length);
}

public static void sort(Object[] array, int h, int t) {
if (h < t) {
Object v = array[h];
int i = h, j = t - 1;
while (i < j) {
while (i < j && bigger(array[j], v)) j--;
array[i] = array[j];
while (i < j && bigger(v, array[i])) i++;
array[j] = array[i];
}
array[i] = v;
sort(array, h, i);
sort(array, i + 1, t);
}
}

private static boolean bigger(Object a, Object b) {
return ((Comparable) a).compareTo(b) >= 0 ? true : false;
}

public static void main(String[] args) {
int len = 10;
Integer[] a = new Integer[len];
for (int i = 0; i < len; i++) {
a[i] = len - i;
}
a[0] = 3;
QuickSort.sort(a);
Arrays.stream(a).forEach(System.out::println);
}
}