merge
大致想法
细节
需要 merge 的 2 组序列存在于同一个数组中,并且是挨在一起的
为了更好的完成 merge 操作,最好将其中 1 组序列备份出来,比如 [begin,mid)
基本实现
情况一:左边先结束 => 左边一结束整个归并就结束
情况二:右边先结束 => 右边一结束就直接将左边按顺序挪到右边去
7.3 基本实现 @SuppressWarnings("unchecked") public class MergeSort<T extends Comparable<T>> extends Sort<T> { private T[] leftArr; @Override protected void sort() { leftArr = (T[]) new Comparable[array.length >> 1]; sort(0, array.length); } /** 对 [begin,end) 位置的元素进行归并排序 */ private void sort(int begin, int end) { if (end - begin < 2) return; int mid = (begin + end) >> 1; sort(begin, mid); sort(mid, end); merge(begin, mid, end); } /** 将 [begin,mid) 和 [mid,end) 范围的序列合并成一个有序序列 */ private void merge(int begin, int mid, int end) { int li = 0, le = mid - begin; int ri = mid, re = end; int ai = begin; //备份左边数组 for (int i = 0; i < le; i++) { leftArr[i] = array[begin + i]; } //如果左边还没有结束(情况一) while (li < le) { //当 ri < re 不成立,就会一直leftArr挪动(情况二) if (ri < re && cmp(array[ri],leftArr[li]) < 0) { array[ai++] = array[ri++]; } else { //注意稳定性 array[ai++] = leftArr[li++]; } } } } 7.4 算法优劣复杂度分析
T(n) = sort() + sort() + merge() => T(n) = T(n/2) + T(n/2) + O(n) => T(n) = 2T(n/2) + O(n) //由于sort()是递归调用,用T表示,由于T(n/2)不好估算,现在要理清T(n)与O(n)之间的关系 T(1) = O(1) T(n)/n = T(n/2) / (n/2) + O(1) //令S(n) = T(n)/n S(1) = O(1) S(n) = S(n/2) + O(1) = S(n/4) + O(2) = S(n/8) + O(3) = S( n/(2^k) ) + O(k) = S(1) + O(log^n) = O(lon^n) T(n) = n*S(n) = O(nlog^n) => 归并排序时间复杂度:O(nlog^n)常见递推式
总结