软件:DrJava
参考书:算法(第四版)
章节:2.2归并排序(以下截图是算法配套视频所讲内容截图)
1:mergesort 归并排序
2:bottom-up mergesort 自底向上的归并排序
3:sorting complexity 排序的复杂度
4:comparators 比较器
5:stability 稳定性
、
1:mergesort 归并排序
1 /************************************************************************* 2 * Compilation: javac Merge.java 3 * Execution: java Merge < input.txt 4 * Dependencies: StdOut.java StdIn.java 5 * Data files: http://algs4.cs.princeton.edu/22merge/tiny.txt 6 * http://algs4.cs.princeton.edu/22merge/words3.txt 7 * 8 * Sorts a sequence of strings from standard input using mergesort. 9 * 10 * % more tiny.txt 11 * S O R T E X A M P L E 12 * 13 * % java Merge < tiny.txt 14 * S O R T E X A M P L E A [ one string per line ] 15 * 16 * % more words3.txt 17 * bed bug dad yes zoo ... all bad yet 18 * 19 * % java Merge < words3.txt 20 * all bad bed bug dad ... yes yet zoo [ one string per line ] 21 * 22 *************************************************************************/ 23 24 public class Merge { 25 26 // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi] 27 public static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) { 28 29 // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays 30 assert isSorted(a, lo, mid); 31 assert isSorted(a, mid+1, hi); 32 33 // copy to aux[] 34 for (int k = lo; k <= hi; k++) { 35 aux[k] = a[k]; 36 } 37 38 // merge back to a[] 39 int i = lo, j = mid+1; 40 for (int k = lo; k <= hi; k++) { 41 if (i > mid) a[k] = aux[j++]; 42 else if (j > hi) a[k] = aux[i++]; 43 else if (less(aux[j], aux[i])) a[k] = aux[j++]; 44 else a[k] = aux[i++]; 45 } 46 47 // postcondition: a[lo .. hi] is sorted 48 assert isSorted(a, lo, hi); 49 } 50 51 // mergesort a[lo..hi] using auxiliary array aux[lo..hi] 52 private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) { 53 if (hi <= lo) return; 54 int mid = lo + (hi - lo) / 2; 55 sort(a, aux, lo, mid); 56 sort(a, aux, mid + 1, hi); 57 merge(a, aux, lo, mid, hi); 58 } 59 60 public static void sort(Comparable[] a) { 61 Comparable[] aux = new Comparable[a.length]; 62 sort(a, aux, 0, a.length-1); 63 assert isSorted(a); 64 } 65 66 67 /*********************************************************************** 68 * Helper sorting functions 69 ***********************************************************************/ 70 71 // is v < w ? 72 private static boolean less(Comparable v, Comparable w) { 73 return (v.compareTo(w) < 0); 74 } 75 76 // exchange a[i] and a[j] 77 private static void exch(Object[] a, int i, int j) { 78 Object swap = a[i]; 79 a[i] = a[j]; 80 a[j] = swap; 81 } 82 83 84 /*********************************************************************** 85 * Check if array is sorted - useful for debugging 86 ***********************************************************************/ 87 private static boolean isSorted(Comparable[] a) { 88 return isSorted(a, 0, a.length - 1); 89 } 90 91 private static boolean isSorted(Comparable[] a, int lo, int hi) { 92 for (int i = lo + 1; i <= hi; i++) 93 if (less(a[i], a[i-1])) return false; 94 return true; 95 } 96 97 98 /*********************************************************************** 99 * Index mergesort 100 ***********************************************************************/ 101 // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi] 102 private static void merge(Comparable[] a, int[] index, int[] aux, int lo, int mid, int hi) { 103 104 // copy to aux[] 105 for (int k = lo; k <= hi; k++) { 106 aux[k] = index[k]; 107 } 108 109 // merge back to a[] 110 int i = lo, j = mid+1; 111 for (int k = lo; k <= hi; k++) { 112 if (i > mid) index[k] = aux[j++]; 113 else if (j > hi) index[k] = aux[i++]; 114 else if (less(a[aux[j]], a[aux[i]])) index[k] = aux[j++]; 115 else index[k] = aux[i++]; 116 } 117 } 118 119 // return a permutation that gives the elements in a[] in ascending order 120 // do not change the original array a[] 121 public static int[] indexSort(Comparable[] a) { 122 int N = a.length; 123 int[] index = new int[N]; 124 for (int i = 0; i < N; i++) 125 index[i] = i; 126 127 int[] aux = new int[N]; 128 sort(a, index, aux, 0, N-1); 129 return index; 130 } 131 132 // mergesort a[lo..hi] using auxiliary array aux[lo..hi] 133 private static void sort(Comparable[] a, int[] index, int[] aux, int lo, int hi) { 134 if (hi <= lo) return; 135 int mid = lo + (hi - lo) / 2; 136 sort(a, index, aux, lo, mid); 137 sort(a, index, aux, mid + 1, hi); 138 merge(a, index, aux, lo, mid, hi); 139 } 140 141 // print array to standard output 142 private static void show(Comparable[] a) { 143 for (int i = 0; i < a.length; i++) { 144 StdOut.println(a[i]); 145 } 146 } 147 148 // Read strings from standard input, sort them, and print. 149 public static void main(String[] args) { 150 String[] a = StdIn.readStrings(); 151 Merge.sort(a); 152 show(a); 153 } 154 }
此方法中,是把数组a分成了前半部分和后半部分。书中并没有特别强调,在进行归并算法前,前后两部分其实已经分别进行了排序,但事实上,他们是已经排序好的。
此算法的精妙之处在于,通过一个aux数组保存数组a中的数据。所以说,此方法其实对内存多占用了N个空间。
private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
if (hi <= lo) return;
int mid = lo + (hi - lo) / 2;
sort(a, aux, lo, mid);
sort(a, aux, mid + 1, hi);
merge(a, aux, lo, mid, hi);
}
我之前一直对上边的程序,耿耿于怀,不知道怎么迭代处理了,后来终于搞清楚了。
例如:lo=0,hi=15,
sort(a,aux,0,15)
sort(a,aux,0,7),
sort(a,aux,0,3),
sort(a,aux,0,1),
sort(a,aux,0,0),
return
sort(a,aux,1,1),
merge(a,aux,1,1)
merge(a,aux,0,1),
sort(a,aux,2,3),
sort(a,aux,2,2)
merge(a,aux,2,2,3)
merge(a,aux,0,1,3)
sort(a,aux,4,7),
sort(a,aux,4,5),
merge(a,aux,4,4,5)
sort(a,aux,6,7),
merge(a,aux,6,6,7)
merge(a,aux,4,4,7)
merge(a,aux,0,3,7)
2:bottom-up mergesort 自底向上的归并排序
递归实现的归并排序是算法设计中分治思想的典型应用。我们将一个大问题分割成一个小问题分别解决,然后用所有的小问题的答案来解决整个大问题。
1 /************************************************************************* 2 * Compilation: javac MergeBU.java 3 * Execution: java MergeBU < input.txt 4 * Dependencies: StdOut.java StdIn.java 5 * Data files: http://algs4.cs.princeton.edu/22merge/tiny.txt 6 * http://algs4.cs.princeton.edu/22merge/words3.txt 7 * 8 * Sorts a sequence of strings from standard input using 9 * bottom-up mergesort. 10 * 11 * % more tiny.txt 12 * S O R T E X A M P L E 13 * 14 * % java MergeBU < tiny.txt 15 * S O R T E X A M P L E A [ one string per line ] 16 * 17 * % more words3.txt 18 * bed bug dad yes zoo ... all bad yet 19 * 20 * % java MergeBU < words3.txt 21 * all bad bed bug dad ... yes yet zoo [ one string per line ] 22 * 23 *************************************************************************/ 24 25 public class MergeBU { 26 27 28 29 // stably merge a[lo..m] with a[m+1..hi] using aux[lo..hi] 30 private static void merge(Comparable[] a, Comparable[] aux, int lo, int m, int hi) { 31 32 // copy to aux[] 33 for (int k = lo; k <= hi; k++) { 34 aux[k] = a[k]; 35 } 36 37 // merge back to a[] 38 int i = lo, j = m+1; 39 for (int k = lo; k <= hi; k++) { 40 if (i > m) a[k] = aux[j++]; 41 else if (j > hi) a[k] = aux[i++]; 42 else if (less(aux[j], aux[i])) a[k] = aux[j++]; 43 else a[k] = aux[i++]; 44 } 45 46 } 47 48 // bottom-up mergesort 49 public static void sort(Comparable[] a) { 50 int N = a.length; 51 Comparable[] aux = new Comparable[N]; 52 for (int n = 1; n < N; n = n+n) { 53 for (int i = 0; i < N-n; i += n+n) { 54 int lo = i; 55 int m = i+n-1; 56 int hi = Math.min(i+n+n-1, N-1); 57 merge(a, aux, lo, m, hi); 58 } 59 } 60 assert isSorted(a); 61 } 62 63 /*********************************************************************** 64 * Helper sorting functions 65 ***********************************************************************/ 66 67 // is v < w ? 68 private static boolean less(Comparable v, Comparable w) { 69 return (v.compareTo(w) < 0); 70 } 71 72 // exchange a[i] and a[j] 73 private static void exch(Object[] a, int i, int j) { 74 Object swap = a[i]; 75 a[i] = a[j]; 76 a[j] = swap; 77 } 78 79 80 /*********************************************************************** 81 * Check if array is sorted - useful for debugging 82 ***********************************************************************/ 83 private static boolean isSorted(Comparable[] a) { 84 for (int i = 1; i < a.length; i++) 85 if (less(a[i], a[i-1])) return false; 86 return true; 87 } 88 89 // print array to standard output 90 private static void show(Comparable[] a) { 91 for (int i = 0; i < a.length; i++) { 92 StdOut.println(a[i]); 93 } 94 } 95 96 // Read strings from standard input, sort them, and print. 97 public static void main(String[] args) { 98 String[] a = StdIn.readStrings(); 99 MergeBU.sort(a); 100 show(a); 101 } 102 }
自底向上的归并排序比较适合用链表组织的数据。想象一下将链表先按大小为1的子链表进行排序,然后使大小为2的子链表,然后使大小为4的子链表等。这种方法只需要重新组织链表链接就能将链表原地排序(不需要创建任何新的链表结点)。
3:sorting complexity 排序的复杂度
作者在视频中提出:计算的复杂度,要从五个方面考虑。
分别为:
1:model of computation:计算模型
2:cost model:时间模型
3:upper bound:上限
4:lower bound:下限
5:optimal algorithm:最佳算法