# 前言
排序算法的成本模型计算的是比较和交换的次数。less()方法对元素进行比较,exch()方法将元素交换位置。
public static void exch(Comparable[] a, int i, int j) {Comparable temp = a[i];a[i] = a[j];a[j] = temp;}public static boolean less(Comparable a, Comparable b) {return a.compareTo(b) < 0;}
# 原地归并的抽象方法
该方法将所有元素复制到了aux[]中,然后再归并回a[]中。方法在归并(第二个 for 循环)进行了 4 个条件判断:
- 左半边用尽,取右半边的元素;
- 右半边用尽,取左半边的元素;
- 右半边的当前元素小于左半边的当前元素,取右半边的元素;
-
* 实现
public static void merge(Comparable[] a, int start, int mid, int end) {int i = start, j = mid + 1;for (int k = start; k <= end; k++) {aux[k] = a[k];}for (int k = start; k<= end; k++) {if (i > mid) a[k] = aux[j++];else if (j > end) a[k] = aux[i++];else if (less(a[j], a[i])) a[k] = aux[j++];else a[k] = a[i++];}}
# 自顶向下的归并排序
自顶向下的归并排序应用了分治的思想,要对数组 a 排序,现将数组分为
a[start, mid]和a[mid + 1, end]两个部分,分别通过递归的调用来将它们单独排序,最后将有序的子数组归并为最终的结果。
* 实现
```java private static Comparable[] aux; // 归并所需的辅助数组
public static void sort(Comparable[] a) { aux = new Comparable[a.length]; // 一次性分配空间 sort(a, 0, a.length - 1); }
private static void sort(Comparable[] a, int start, int end) { if (end <= start) return;
int mid = (start + end) / 2;sort(a, start, mid); // 将左半边排序sort(a, mid + 1, end); // 将右半边排序merge(a, start, mid, end); // 归并结果
}
<a name="Rk8vt"></a># # 自底向上的归并排序实现归并排序的另一种方法是先归并那些微型数组,然后在成对归并得到的子数组,如此这般多次的遍历整个数组,直到我们将整个数组合并到一起。自底向上的归并排序比较适合链表组织的数据。> 可以将链表按照大小为 1 的子链表进行排序,然后是大小为 2 的链表,然后是大小为 4 的子链表等。<a name="uNxhR"></a>## * 实现```javapublic class MergeBU {private static Comparable[] aux;public static void sort(Comparable[] a) {int N = a.length;aux = new Comparable[N];for (int size = 1; size < N; size = 2 * size) {for (int start = 0; start < N - size; star += 2 * size) {merge(a, start, start + size - 1, Math.max(start + 2 * size - 1, N - 1);}}}}
