快速排序(递归版)
随名为快速,实际情况下时间复杂度较高。需要寻找合适的阈值,一般课选择首元素、中间元素或尾元素作为阈值,也可以随机选择一个元素作为阈值,以免退化到极端情况。
算法
- 选择array中的一个阈值,一般为中位值,可随机选择,比中位值小的对象放在序列X中,比中位值大的对象放在Y中
- 若子序列X包含超过一个对象,递归对子序列X排序
- 若子序列Y包含超过一个对象,递归对子序列Y排序
- 合并子序列X、Y,最终得到排序后的序列
算法测试
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] a = { 13, 90, -45, 10, 9, 25, 8, 335, 7, 728, 41, -35, 6, 45, 5, 4, 3, 2, 1, 0, -1, 35 };
a = fast_sort_recurse(a);
System.out.println(Arrays.toString(a));
}
public static int[] fast_sort_recurse(int[] a) {
if (a.length == 1) return a;
System.out.println(Arrays.toString(a));
// 寻找数组a的中位数
// 由于精确寻找中位数代价太大,
// 因此随机选择一个元素作为中位数。
int midIndex = (int) (Math.random() * a.length);
System.out.println("midIndex = " + midIndex);
int mid = a[midIndex];
int[] work = new int[a.length];
int down = 0, up = a.length - 1;
for (int item : a) {
if (item <= mid) {
work[down++] = item;
} else {
work[up--] = item;
}
}
// 定义左右子节点
int[] al = null, ar = null;
if (down != 0) {
al = new int[down];
for (int i = 0; i < down; i++) {
al[i] = work[i];
}
al = fast_sort_recurse(al);
}
if (a.length - up - 1 != 0) {
ar = new int[a.length - up - 1];
for (int j = 0; j < a.length - up - 1; j++) {
ar[j] = work[j + up + 1];
}
ar = fast_sort_recurse(ar);
}
if (al != null && ar != null) {
return merge_array(al, ar);
} else if (al == null && ar != null) {
return ar;
} else if (al != null && ar == null) {
return al;
} else {
return null;
}
}
// 合并两个有序列
private static int[] merge_array(int[] arrLeft, int[] arrRight) {
int m = arrLeft.length;
int n = arrRight.length;
int[] arrMerge = new int[m + n];
int i = 0, j = 0;
while (i < m && j < n) {
if (arrLeft[i] < arrRight[j]) {
arrMerge[i + j] = arrLeft[i];
i++;
} else {
arrMerge[i + j] = arrRight[j];
j++;
}
}
if (i < m) {
while (i < m) {
arrMerge[i + n] = arrLeft[i];
i++;
}
} else {
while (j < n) {
arrMerge[j + m] = arrRight[j];
j++;
}
}
return arrMerge;
}
}