# 算法 - 归并排序

  1 public class MergeSort<T extends Comparable> {
2
3     private T[] sort(T[] arr, int left, int right) {
4         // 拆分中点
5         int middle = (right + left) / 2;
6         // 如果只有一个数，即左标右标相等，跳出递归
7         if (left == right) {
8             return (T[]) new Comparable[]{arr[left]};
9         }
10         printSplit(arr, left, middle);
11         // 左子列递归
12         T[] leftArr = sort(arr, left, middle);
13         printSplit(arr, middle + 1, right);
14         // 右子列递归
15         T[] rightArr = sort(arr, middle + 1, right);
16         // 合并
17         return merge(leftArr, rightArr);
18     }
19
20     private T[] merge(T[] leftArr, T[] rightArr) {
21         int lengthLeft = leftArr.length;
22         int lengthRight = rightArr.length;
23         // 左子列的游标
24         int left = 0;
25         // 右子列的游标
26         int right = 0;
27         // 新建数组的游标
28         int cur = 0;
29         // 新建放合并元素的数组
30         T[] mergeArr = (T[]) new Comparable[leftArr.length + rightArr.length];
31         // 放满了就退出
32         while (cur < mergeArr.length) {
33             // 右标移动到末尾了，就把左子列的都放到数组里
34             if (right == lengthRight) {
35                 while (left < lengthLeft) {
36                     mergeArr[cur] = leftArr[left];
37                     left++;
38                     cur++;
39                 }
40             }
41             // 左子列的数比右子列的小，放到数组里，移动游标
42             while (left < lengthLeft && leftArr[left].compareTo(rightArr[right]) <= 0) {
43                 mergeArr[cur] = leftArr[left];
44                 left++;
45                 cur++;
46             }
47             // 左子列移动到末尾了，就把右子列的都放到数组里
48             if (left == lengthLeft) {
49                 while (right < lengthRight) {
50                     mergeArr[cur] = rightArr[right];
51                     right++;
52                     cur++;
53                 }
54             }
55             // 右子列的数比左子列的小，放到数组里，移动游标
56             while (right < lengthRight && rightArr[right].compareTo(leftArr[left]) < 0) {
57                 mergeArr[cur] = rightArr[right];
58                 right++;
59                 cur++;
60             }
61         }
62         printMerge(mergeArr);
63         return mergeArr;
64     }
65
66     private void printSplit(T[] arr, int left, int right) {
67         String[] stringArr = new String[]{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "};
68         for (int i = left; i <= right; i++) {
69             stringArr[i] = "*";
70         }
71         for (T n : arr) {
72             System.out.print(n);
73         }
74         System.out.println();
75         for (String s : stringArr) {
76             System.out.print(s);
77         }
78         System.out.println(" => 拆分");
79     }
80
81     private void printMerge(T[] arr) {
82         for (T n : arr) {
83             System.out.print(n);
84         }
85         System.out.print(" => 合并");
86         System.out.println();
87     }
88
89     public void sort(T[] arr) {
90         Comparable[] newArr = sort(arr, 0, arr.length - 1);
91         for (int i = 0; i < arr.length; i++) {
92             arr[i] = (T) newArr[i];
93         }
94     }
95
96     public static void main(String[] args) {
97         Integer[] arr = new Integer[]{1, 3, 8, 7, 6, 9, 5, 4, 3, 2, 0};
98         MergeSort ms = new MergeSort();
99         ms.sort(arr);
100     }
101
102     /**
103      * 13876954320
104      * ******      => 拆分
105      * 13876954320
106      * ***         => 拆分
107      * 13876954320
108      * **          => 拆分
109      * 13876954320
110      * *           => 拆分
111      * 13876954320
112      *  *          => 拆分
113      * 13 => 合并
114      * 13876954320
115      *   *         => 拆分
116      * 138 => 合并
117      * 13876954320
118      *    ***      => 拆分
119      * 13876954320
120      *    **       => 拆分
121      * 13876954320
122      *    *        => 拆分
123      * 13876954320
124      *     *       => 拆分
125      * 67 => 合并
126      * 13876954320
127      *      *      => 拆分
128      * 679 => 合并
129      * 136789 => 合并
130      * 13876954320
131      *       ***** => 拆分
132      * 13876954320
133      *       ***   => 拆分
134      * 13876954320
135      *       **    => 拆分
136      * 13876954320
137      *       *     => 拆分
138      * 13876954320
139      *        *    => 拆分
140      * 45 => 合并
141      * 13876954320
142      *         *   => 拆分
143      * 345 => 合并
144      * 13876954320
145      *          ** => 拆分
146      * 13876954320
147      *          *  => 拆分
148      * 13876954320
149      *           * => 拆分
150      * 02 => 合并
151      * 02345 => 合并
152      * 01233456789 => 合并
153      *
154      * 136789 - 02345 => 稳定性和合并过程说明
155      * ^      . ^     => []
156      * ^      .  ^    => 右比左小 => [0] => 【包含赋值和移动，下同】
157      *  ^     .  ^    => 左比右小 => [0, 1]
158      *  ^     .   ^   => 右比左小 => [0, 1, 2]
159      *  ^     .   ^   => 左右相等，左侧含等号，右侧不含，跳过 => [0, 1, 2]
160      *   ^    .   ^   => 左右相等，进入 => [0, 1, 2, 3]
161      *   ^    .    ^  => 右比左小 => [0, 1, 2, 3, 3] => 顺序未改变，稳定
162      *   ^    .     ^ => 右比左小 => [0, 1, 2, 3, 3, 4]
163      *   ^    .      ^=> 右比左小 => [0, 1, 2, 3, 3, 4, 5] => 右标 = 右子列长度
164      *    ^   .       => 左子列剩余元素移入数组 => [0, 1, 2, 3, 3, 4, 5, 6]
165      *     ^  .       => 左子列剩余元素移入数组 => [0, 1, 2, 3, 3, 4, 5, 6, 7]
166      *      ^ .       => 左子列剩余元素移入数组 => [0, 1, 2, 3, 3, 4, 5, 6, 7, 8]
167      *       ^.       => 左子列剩余元素移入数组 => [0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9] => 左标 = 左子列长度
168      * 游标cur = 数组长度，退出循环，完成合并过程
169      *
170      * 每层遍历一遍，遍历了logn次
171      * => 遍历次数：nlogn
172      * => 时间复杂度：O(nlogn)
173      * => 稳定性：稳定
174      *
175      */
176
177 }

posted @ 2020-04-28 14:01  SamNicole1809  阅读(69)  评论(0编辑  收藏