归并排序(Merge Sort)

Posted by 余腾 on 2019-02-22
Estimated Reading Time 2 Minutes
Words 566 In Total
Viewed Times

归并排序

归并排序(Merging Sort)就是将两个或者两个以上的有序表合并成一个有序表的过程。2-路归并

归并排序算法的思想是:
假设初始序列含有n个记录,则可看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的子序列;
再两两归并, ….., 如此重复,直至得到一个长度为n的有序序列为止。


代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class MergeSort {
public static void mergeSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
mergeSort(arr, 0, arr.length - 1);
}

private static void mergeSort(int[] arr, int left, int right){
if(left == right){
return;
}
int mid = left + ((right-left) >> 1); // <--> (l+r)/2
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
// left - mid mid+1 - right 两个序列已经排好序,但整体无序
// merge的过程就是将两个序列排序
merge(arr, left, mid, right);
}

private static void merge(int[] arr, int left, int m, int right) {
// 申请辅助数组,存放合并后的序列
int[] help = new int[right - left + 1];
int i= 0;
int p1 = left;
int p2 = m + 1;
while(p1 <= m && p2 <= right){
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
// 两个必有且只有一个越界
// 两个循环只会执行一个
while (p1 <= m) {
help[i++] = arr[p1++];
}
while (p2 <= right) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[left + i] = help[i];
}
}
}

动画演示

图片来源:五分钟学算法 十大经典排序


merge过程


p1,p2每次只会移动一个,所以必定会有一个越界。如果p1耗尽,需要把p2后面内容拷贝至help数组,反之。

1
2
3
4
5
6
while (p1 <= m) {
help[i++] = arr[p1++];
}
while (p2 <= right) {
help[i++] = arr[p2++];
}

时间复杂度

当有n个记录时,需进行⌈log2n⌉躺归并排序,其关键字比较次数不超过n,元素移动次数都是n,
因此,归并排序的时间复杂度为O(nlog2n)。


空间复杂度

用顺序表实现归并排序时,需要和待排序记录个数相等的辅助存储空间,所以空间复杂度为O(n)。


特点

归并排序是一种稳定的排序。

感谢阅读


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !