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


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

  • 相关阅读:
    OSDEV网站提供了非常丰富的操作系统方面知识
    一本牛X的逆向工程权威指南
    视频时序计算器Video Timings Calculator
    编写C编译器入门教程Let's write a compiler
    开源USB协议栈CherryUSB
    基于STM32动态加载实现原理
    云上弹性高性能计算,支持生命科学产业高速发展、降本增效
    Apsara Stack 同行者专刊 | 政企混合云技术架构的演进和发展
    DataWorks开发ODPS SQL开发生产环境自动补全ProjectName
    代码注释的艺术,优秀代码真的不需要注释吗?
  • 原文地址:https://www.cnblogs.com/mrchige/p/6001272.html
Copyright © 2020-2023  润新知