复习八大基础排序算法。分类:
- 插入类(直接插入、希尔排序)
- 选择类(直接选择、堆排序)
- 交换类(冒泡排序、快速排序)4. 归并排序
- 还有外部排序(桶排序?)
复杂度分析
- 空间复杂度: 2N + O(logN) (原始数组+辅助数组+递归过程)
时间复杂度: Nlog(N)
Principle: T(N) = 2*T(N/2) + N (两个子问题+ merge)
证明可以画递归树、或代数演算、或归纳法(最容易推导)
代码如下
递归地(TopDown)
public static void mergeSort(Comparable[] a) { aux = new Comparable[a.length]; sort(a, 0, a.length - 1, 0); } private static void sort(Comparable[] a, int lo, int hi, int dep) {for (int i = 0; i < dep; i++) StdOut.print(" ");StdOut.println(String.format("sort(a[], %d, %d)", lo, hi)); if (hi <= lo) return; int mid = (lo + hi) / 2; sort(a, lo, mid, dep+1); sort(a, mid + 1, hi, dep+1); merge(a, lo, mid, hi); } private static void merge(Comparable[] a, int lo, int mid, int hi) { assert isSorted(a, lo, mid); assert isSorted(a, mid+1, hi); // 复制a[]到aux[] for (int k = lo; k <= hi; k++) aux[k] = a[k]; // 归并 int i = lo, j = mid+1; for (int k = lo; k <= hi; k++) { if (i > mid) a[k] = aux[j++]; //左半边遍历完了 else if (j > hi) a[k] = aux[i++]; //右半边遍历完了 else if (less(aux[i], aux[j])) a[k] = aux[i++]; // a[i]比a[j]小 else a[k] = aux[j++]; // j 位置较小 } assert isSorted(a); }
图示
非递归地(BottomUp)
public static void bottomUpMergeSort(Comparable[] a) { aux = new Comparable[a.length]; int N = a.length; for (int sz = 1; sz < N; sz += sz) // sz是子序列的长度,依次为 1, 2, 4, 8, 16, ... ,直到 N for (int lo = 0; lo < N - sz + 1; lo += 2*sz) // lo是合并所得子序列的下标,如sz=2时,lo依次为 0, 4, 8,... merge(a, lo, lo+sz-1, Math.min(lo+2*sz-1, N-1)); }