归并排序的核心思想还是蛮简单的。如果要排序一个数组,我们先把数组从中间分成前后两
部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有
序了。
如下图,针对数组:11、 8、 3、 9、7、1、2、5,归并排序的过程如下
![](https://img-blog.csdnimg.cn/20200517133743621.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNzc1Nzc0,size_16,color_FFFFFF,t_70)
伪代码如下:
void test(){
merge_sort(data,0,data.length-1)
}
//对 数组data 下标为 r 到 q 进行排序
void merge_sort(data,r,q){
if(r>=q)
return;
int mid = (r + q)/2
merge_sort(data,r,mid)
merge_sort(data,mid+1,q)
merge(data,r,mid,mid+1,q)
}
//将已经有序的 data[r1] ... data[q1] , data[r2] ... data[q2] ,合并排序为有序数组
void merge(data,r1,q1,r2,q2){
}
Java代码如下:
public class SortTest {
private void swap(int[] data,int i,int j){
int tmp = data[i];
data[i] = data[j];
data[j] = tmp;
}
public void printArray(int[] data){
for(int d:data){
System.out.print(d+" ");
}
System.out.println();
}
/**
* 归并排序
*/
public void mergeSort(int[] data,int r1,int q1,int r2,int q2){
int start1 = r1;
int start2 = r2;
int start = 0;
int[] tmp = new int[q2-r1+1];
while (start1<=q1 && start2 <=q2){
if(data[start1] <= data[start2]){
tmp[start++] = data[start1++];
}else {
tmp[start++] = data[start2++];
}
}
while (start1<=q1){
tmp[start++] = data[start1++];
}
while (start2<=q2){
tmp[start++] = data[start2++];
}
for(int i=r1;i<=q2;i++){
data[i] = tmp[i-r1];
}
}
public void merge(int[] data,int r,int q){
if(r>=q)
return;
int middle = (r+q)/2;
merge(data,r,middle);
merge(data,middle+1,q);
mergeSort(data,r,middle,middle+1,q);
}
/**
* 归并排序
*/
@Test
public void test4(){
int[] data = {55,76,34,66,22,31,13,25,90,87,56,65,66};
//int[] data = {6,7,8,9,1,2,30,40,50};
//mergeSort(data,0,3,4,8);
merge(data,0,data.length-1);
printArray(data);
}
}
结果:
13 22 25 31 34 55 56 65 66 66 76 87 90
分析:
第一,归并排序是稳定的排序算法吗?
归并排序稳不稳定关键要看
merge() 函数,也就是两个有序子数组合并成一个有序数组的那部分代码。
我们可以控制该函数在合并时,保证相同值元素
的先后顺序不变。所以,归并排序是一个稳定的排序算法。
第二,归并排序的时间复杂度是多少?
从我们的原理分析和伪代码可以看出,归并排序的执行效率与要排序的原始数组的有序程度
无关,所以其时间复杂度是非常稳定的,不管是最好情况、最坏情况,还是平均情况,时间
复杂度都是 O(nlogn)。
第三,归并排序的空间复杂度是多少?
归并排序的时间复杂度任何情况下都是 O(nlogn),看起来非常优秀。(待会儿你会发现,
即便是快速排序,最坏情况下,时间复杂度也是 O(n
2
)。)但是,归并排序并没有像快排那
样,应用广泛,这是为什么呢?因为它有一个致命的“弱点”,那就是归并排序不是原地排
序算法。