算法学习记录2 归并排序

自己的理解

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

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

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

3.把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

 

posted @ 2017-02-27 11:17  abcwt112  阅读(226)  评论(0编辑  收藏  举报