归并排序
1/**
2 * 归并排序的Java实现
3 * <p>
4 * 归并排序的思想是分治+递归。若要将数组排序,归并排序的思想
5 * 就是将数组拆分为2个不同的数组(一般是从中拆分),然后分别将2个数组排序,
6 * 最后将已经排序的数组合并
7 * </p>
8 *
9 * @author wangy
10 * @version 1.0
11 * @date 2021/7/6 / 19:46
12 */
13public class MergeSort {
14
15 static void sort(int[] a) {
16 int l = a.length;
17 sort(a, 0, l - 1);
18 }
19
20
21 private static void sort(int[] a, int p, int r) {
22 if (p >= r) return;
23 int m = (p + r) / 2;
24 // 分治
25 sort(a, p, m);
26 sort(a, m + 1, r);
27 // 合并
28// merge(a, p, m, r);
29 mergeBySentinel(a, p, m, r);
30 }
31
32 private static void merge(int[] a, int p, int m, int r) {
33 int pos = 0;
34 int left = p;
35 int right = m + 1;
36 // 需要额外的空间
37 int[] tmpA = new int[r - p + 1];
38 while (left <= m && right <= r) {
39 if (a[left] > a[right]) {
40 tmpA[pos++] = a[right++];
41 } else {
42 tmpA[pos++] = a[left++];
43 }
44 }
45 // 分治数组是否有剩余元素,若有,全部添加到tmpA末尾
46 while (left <= m) {
47 tmpA[pos++] = a[left++];
48 }
49 while (right <= r) {
50 tmpA[pos++] = a[right++];
51 }
52 // 将缓存数据写到原始数组中「对应的位置」
53 // p, m, r
54 /*for (int i = r - p; i >= 0; i--, r--) {
55 a[r] = tmpA[i];
56 }*/
57 // 等效代码
58 for (int i = 0; i < tmpA.length; i++) {
59 a[p + i] = tmpA[i];
60 }
61 // 打印合并的过程
62 System.out.println("merge ---" + Arrays.toString(tmpA));
63 }
64
65 // 为2个分治数组分别添加哨兵
66 public static void mergeBySentinel(int[] a, int p, int m, int r) {
67 // 2个数组分别多申请一个空间,用来放置哨兵
68 int[] leftArray = new int[m - p + 2];
69 int[] rightArray = new int[r - m + 1];
70 // 拷贝元素
71 for (int i = p; i <= m; i++) {
72 leftArray[i - p] = a[i];
73 }
74 for (int i = m + 1; i <= r; i++) {
75 rightArray[i - m - 1] = a[i];
76 }
77 // 放置哨兵
78 leftArray[leftArray.length - 1] = Integer.MAX_VALUE;
79 rightArray[rightArray.length - 1] = Integer.MAX_VALUE;
80
81 // 合并元素
82 int li = 0, ri = 0;
83 int pos = p;
84 while (pos <= r) {
85 // 哨兵元素的目的在于,始终可以保证2个分治数组的元素遍历完毕
86 if (leftArray[li] <= rightArray[ri])
87 a[pos++] = leftArray[li++];
88 else
89 a[pos++] = rightArray[ri++];
90 }
91 }
92
93 public static void main(String[] args) {
94 int[] a = new int[]{3, 7, 2, 15, 9, 13, 1, 24, 77, 16};
95 System.out.println(Arrays.toString(a));
96 MergeSort.sort(a);
97 System.out.println(Arrays.toString(a));
98 }
99}