算法学习记录2 归并排序

时间:2021-03-24 11:21:46

自己的理解

归并排序感觉比快速排序简单一点...反正我觉得好理解一点..

1.把1个要排序的数组拆分成2个要排序的小数组(可以直接取中间元素,分成2个一样长度的小数组).

2.对每个小数组继续拆分,拆分到只有一个元素.

3.把2个小数组重合归并成一个排好序的大数组,然后这个大数组再和其他大数组归并成一个更大的数组....循环下去最后归并成一开始完整的数组.

 

实现

算法学习记录2 归并排序算法学习记录2 归并排序
 1 package algorithm;
2
3 import java.util.Arrays;
4
5 /**
6 * 合并排序
7 *
8 * @author jyzjyz12@163.com
9 * @since 2017年2月27日 上午10:25:48
10 */
11 public class MergeSortTest1 {
12 public static void main(String[] args) {
13 int[] arr1 = { 4, 7, 5, 6, 1, 3, 8 };
14 int[] arr2 = { 7, 6, 5, 4, 3, 2, 1 };
15 int[] arr3 = { 5, 9, 3, 7, 8, 6, 1, 2, 4 };
16 int[] arr4 = { 13, 2, 5, 4, 88, 76, 68, 87, 55, 88, 88, 77, 67, 99, 100, 5, 53, 52, 51, 66 };
17 sort(arr1);
18 sort(arr2);
19 sort(arr3);
20 sort(arr4);
21 System.out.println(Arrays.toString(arr1));
22 System.out.println(Arrays.toString(arr2));
23 System.out.println(Arrays.toString(arr3));
24 System.out.println(Arrays.toString(arr4));
25 }
26
27 public static void sort(int[] arr) {
28 sort(arr, 0, arr.length - 1);
29 }
30
31 /**
32 * 排序,可以只排序low到high的位置的数字
33 *
34 * @param arr
35 * 待排序数组
36 * @param low
37 * 要排序数组的开始下标位置
38 * @param high
39 * 要排序数组的终止下标位置
40 */
41 private static void sort(int[] arr, int low, int high) {
42 // 先把数组拆分再合并
43 if (low == high) { // 当数组只有1个元素的时候不需要再拆分
44 return;
45 }
46 int mid = (low + high) / 2;// 准备把数组拆分成2个小部分
47 sort(arr, low, mid);// 再把前半部分再拆分成1半和1半
48 sort(arr, mid + 1, high);// 再把后半部分再拆分成1半和1半
49 merge(arr, low, high, mid);// 把各自排好序的两部分合并起来.合并时候也需要重新排下序,因为虽然2个小部分是排好序的,但是不能保证一个小部分的每个元素都比另外一部分大或者小,可能也有交叉.
50 }
51
52 /**
53 * 把各自排好序的2部分合并起来(需要重新排下序)
54 *
55 * @param arr
56 * 带排序数组
57 * @param low
58 * 两部分最小的下标
59 * @param high
60 * 两部分最大的下标
61 * @param mid
62 * 左半部分最后一个数字的下标
63 */
64 private static void merge(int[] arr, int low, int high, int mid) {
65 int[] temp = new int[high - low + 1]; // 2部分总共有多少个数字,排好序存放在这个数组里
66 int leftPointer = low;// 左半部分最小的下标
67 int rightPointer = mid + 1;// 右半部分最小的下标
68 int currPointer = 0;// 遍历temp用
69 while (leftPointer <= mid && rightPointer <= high) { // 左半部分循环结束或者右半部分循环结束
70 if (arr[leftPointer] <= arr[rightPointer]) { // 左边数组的数字<=右边数组的数字
71 temp[currPointer++] = arr[leftPointer++];// 把左边的数字放到temp中,然后currPointer指向temp中下一个空着的位置,左边数字的指针向后移动
72 } else {// 左边数组的数字>右边数组的数字
73 temp[currPointer++] = arr[rightPointer++];// 把右边的数字放到temp中,然后currPointer指向temp中下一个空着的位置,右边数字的指针向后移动
74 }
75 }
76 // while结束的时候肯定至少有一个数组所有元素已经全部放到temp里了
77 if (leftPointer > mid) { // 如果左边的数组已经全部拷贝到temp里了
78 for (int i = rightPointer; i <= high;) {
79 temp[currPointer++] = arr[i++];// 把右边剩下的元素拷贝到temp里
80 }
81 }
82
83 if (rightPointer > high) { // 如果右边的数组已经全部拷贝到temp里了
84 for (int i = leftPointer; i <= mid;) {
85 temp[currPointer++] = arr[i++];// 把左边剩下的元素拷贝到temp里
86 }
87 }
88
89 // 把temp覆盖回arr的low-high的位置
90 int tempPointer = low;
91 for (int i = 0; i < temp.length; i++) {
92 arr[tempPointer++] = temp[i];
93 }
94 }
95 }
View Code