算法第四版学习笔记之归并算法

软件: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:最佳算法

原文地址:https://www.cnblogs.com/mrchige/p/6001272.html