Merge Sort 根本思路(设计算复杂度为 T(n)):
1) 序列一分为二 //计算复杂度为O(1);
2) 子序列递归排序 //计算复杂度为 2*T(n/2);
3) 合并有序子序列 // 计算复杂度为 O(n);
因此可以得出 T(n) = 2*T(n/2) + O(n);
则可得 T(n) = O(n*log(n))
在归并排序中最核心的问题就是如何合并两个有序的序列,我们利用的方法是二路归并算法。
简单来说就是:只比较两个序列的开头位置,取出其中小的那一个,然后循环运行,知道两个序列归并到一起。
一下是C语言的代码:
//
// main.c
// mergeSortV2
//
// Created by HanXia on 18/3/14.
// Copyright © 2018年 HanXia. All rights reserved.
//
#include <stdio.h>
void merge(int *a, int lo, int mid, int hi);
void mergeSort(int *a, int lo, int hi){
if (hi - lo <= 1){
return;
}
else {
int mid = (hi + lo) >> 1;
//将问题一分为二
mergeSort(a, lo, mid); //递归调用mergeSort函数
mergeSort(a, mid,hi); //递归调用mergeSort函数
merge(a, lo, mid, hi); //归并两个序列
}
}
//二路归并算法
void merge(int *a, int lo, int mid, int hi){
int lb = mid - lo;
//定义B数组将一部分数据copy出来 以下C数组为a[mid,hi] A[lo, hi]
int B[lb];
for(int i = 0; i < lb; i++){
B[i] = a[lo + i];
}
//因为我们并没有开辟新的C数组,所以当B 插入完毕后算法结束
//同时一下判断 hi <= k 与 k < hi 相当于在 a[hi] 设置为一个无穷大的数
//以便于在C归并完后可以顺利归并B数组在正确的位置
for(int i = lo, j = 0, k = mid; j < lb;){
if (hi <= k || B[j] <= a[k]){ //这里的a[k]为C数组部分
//B 数组中的首相小于等于C数组中首相(注如果此时数组C以及插入完毕,则总是成立)
a[i] = B[j]; //取出B数组中的首相
j++;
i++;
}
if (k < hi && a[k] < B[j]){ //
a[i] = a[k];
i++;
k++;
}
}
}
int main(int argc, const char * argv[]) {
int a [10] = {1, 2, 4, 5, 3, 2, 5, 8, 10, 1};
int lo = 2;
int hi = 8;
mergeSort(a, lo, hi);
for(int i = lo ; i < hi; i++){
printf("a[%d] = %d\n",i,a[i]);
}
return 0;
}
输出为:
a[2] = 2
a[3] = 3
a[4] = 4
a[5] = 5
a[6] = 5
a[7] = 8