介绍
归并排序:归并字面意思“回归 ”“合并 ”,把有序的两个或者多个序列合并为一个序列。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。那么什么是分治法呢?
分治法
分治法:将原问题分解为几个规模较小但类似于原问题的子问题,递归的求解这些子问题,然后在合并这些子问题的解来建立原问题的解。
分治模式在每层递归都有三个步骤:
- 分解:把原问题分解若干子问题;
- 解决:把若干子问题解决;
- 合并:把若干问题的解合并。
归并分析
归并排序的核心思想采用分治法。我们通过一个例子来深入的认识。比如现在有一组数 [30, 55, 65, 40, 25, 80, 26, 35],对这些数通过分治法的思想解决排序,遵循三个原则:
- 分解:把需要排序的一组数分解为若干序列,例如[30, 55] , [65, 40] ……;
- 解决:把分解的若干序列按照规则排序,例如从小到大:[30, 55] , [40 65]……;
- 合并:在把若干有序子序列合并为一组数,就完成我们的排序。
下面我们将通过图解来理解这个过程:
代码实现
实现归并排序,这里分为两步,方便理解: 第一步:实现两个有序序列合并;第二步:实现一组数据的排序
实现两个有序序列合并
例如:两个数组 a[min … mid] 和 b[mid … max] 实现有序合并
//将有序数组a[]和b[]合并到c[]中
-(void) mergeArray(firArr:Array, secArr:Array, finshArr:Array){
firArrCount = firArr.count;
secArrCount = secArr.count;
int i, j, k;
i = j = k = 0;
while (i < firArrCount && j < secArrCount)
{
if (firArr[i] < secArr[j]) {
finshArr[k++] = firArr[i++];
}else {
finshArr[k++] = secArr[i++];
}
}
while (i < firArrCount)
finshArr[k++] = firArr[i++];
while (j < secArrCount)
finshArr[k++] = secArr[i++];
}
以上这段代码比较好理解,题目中只要是两个有序的两个数组都可以完成排序,下面我们将实现一组数据的排序。
实现一组数据的排序
例如:现在有数组a[n],使用归并排序完成排序
//实现一组数的排序我们需要对以上两个有序数组排序的代码进行修改添加参数,参数其实就是使用二分法完成数组的分解(也就是分治法的分解原理)
//实现排序合并
-(void) mergeArray(arr:NSArray, first:int, mid:int, last:int, tempArr:NSArray){
int i = first, j = mid + 1;
int m = mid, n = last;
int k = 0;
while (i <= m && j <= n)
{
if (a[i] <= a[j])
tempArr[k++] = a[i++];
else
tempArr[k++] = a[j++];
}
while (i <= m)
tempArr[k++] = a[i++];
while (j <= n)
tempArr[k++] = a[j++];
for (i = 0; i < k; i++)
a[first + i] = tempArr[i];
}
//用递归采用分治法中的分解对数据分解成若干子序列然后排序
-(void) mergeSort(arr:NSArray, first:int, last:int, tempArr:NSArray) {
if (first < last)
{
int mid = (first + last) / 2;
mergeSort(arr, first, mid, tempArr); //左边有序
mergeSort(arr, mid + 1, last, tempArr); //右边有序
mergeArray(arr, first, mid, last, tempArr); //再将二个有序数列合并
}
}
对数组a[n]排序
-(void)test{
//创建完成排序数组
NSMutableArray *finshArr = [[NSMutableArray alloc] initWithCapacity:n];
//对a[n]排序
mergeSort(a, 0, n - 1, finshArr);
}
以上代码是Objective-c语言编写,以上代码没有运行,知识按照思路书写完成,我最近的项目已经使用swift一年多了,以后我将以swift形式编写伪代码。
PS
以上我们对归并排序介绍原理和代码实现,那么这个排序的效率怎么样呢,我们又将如何使用科学有效的方法对一个算法进行分析,来让我们更好的理解算法?