您的位置:首页 > 其它

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

2016-10-26 17:45 447 查看
软件: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
;
124         for (int i = 0; i < N; i++)
125             index[i] = i;
126
127         int[] aux = new int
;
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),

[b]merge(a,aux,6,6,7)[/b]

[b] [b]merge(a,aux,4,4,7)[/b][/b]

[b][b] [b]merge(a,aux,0,3,7)[/b][/b][/b]

[b][b][b]2:bottom-up mergesort 自底向上的归并排序[/b][/b][/b]

递归实现的归并排序是算法设计中分治思想的典型应用。我们将一个大问题分割成一个小问题分别解决,然后用所有的小问题的答案来解决整个大问题。

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
;
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:最佳算法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: