定义
归并就是将两个或多个有序的序列合并成一个有序序列的过程。
二路归并排序是面试中考查最多的排序算法之一。
归并排序有两种:
1、一般归并排序,空间复杂度O(n)
2、原地归并排序,空间复杂度O(1)
一般归并排序
基本思想:将两个或者两个以上的有序表合成一个新的有序表。
归并排序无论是顺序存储还是链式存储结构都有较好的性能。
时间复杂度:O(nlogn)
空间复杂度:O(n)
是否稳定:是
举例说明:对序列{49,38,65,97,76,13,27}共七个元素的无序序列进行归并排序。
其过程如下所示:
- 初始状态:[49] [38] [65] [97] [76] [13] [27] ——>相邻两个数分为一组,归并,则得到
- 一趟归并:[49, 38] [65, 97] [13, 46] [27] ——>相邻两组分为一组,归并
- 二趟归并:[38, 49, 65, 97] [13, 27, 46] ——>相邻两组分为一组,归并
- 三趟归并:[13, 27, 38, 49, 65, 76, 97] ——>完成
从上面的分析,容易看出,归并排序是个递归的过程。递归过程的有两步:分割 和 合并。
由此可以写出以下代码:
void mSort(int Record[], int temp[], int begin, int end)
{
if(begin < end)
{
int mid = (begin + end)/2;
mSort(Record, temp, begin, mid);
mSort(Record, temp, mid+1, end);
merge(Record, temp, begin, mid, end);
}
}
分析:这段代码很简单,共三个步骤:
1、将左半部分分割;
2、将有半部分分割;
3、将左右两半合并;
其中,temp是和Record一样大小的辅助数组。
下面来看下 合并操作。
合并两个有序序列p , q的过程很简单,直接看代码:
(注意:需要使用p.length + q.length的辅助空间)
void merge(int Record[], int temp[], int begin, int mid, int end)
{
int lBegin = begin, lEnd = mid, rBegin = mid+1, rEnd = end;
int k = begin;
while(lBegin <= lEnd && rBegin <= rEnd)
{
if(Record[lBegin] <= Record[rBegin])
temp[k++] = Record[lBegin++];
else
temp[k++] = Record[rBegin++];
}
while(lBegin <= lEnd)
temp[k++] = Record[lBegin++];
while(rBegin <= rEnd)
temp[k++] = Record[rBegin++];
while(begin <= end)
{
Record[begin] = temp[begin];
begin++;
}
}
以上就是一般归并排序的核心过程。
完整代码:
//合并子函数
void merge(int Record[], int temp[], int begin, int mid, int end)
{
int lBegin = begin, lEnd = mid, rBegin = mid+1, rEnd = end;
int k = begin;
while(lBegin <= lEnd && rBegin <= rEnd)
{
if(Record[lBegin] <= Record[rBegin])
temp[k++] = Record[lBegin++];
else
temp[k++] = Record[rBegin++];
}
while(lBegin <= lEnd)
temp[k++] = Record[lBegin++];
while(rBegin <= rEnd)
temp[k++] = Record[rBegin++];
while(begin <= end)
{
Record[begin] = temp[begin];
begin++;
}
}
//分割子函数
void mSort(int Record[], int temp[], int begin, int end)
{
if(begin < end)
{
int mid = (begin + end)/2;
mSort(Record, temp, begin, mid);
mSort(Record, temp, mid+1, end);
merge(Record, temp, begin, mid, end);
}
}
//归并排序
void mergeSort(int Record[], int length)
{
if(Record == NULL || length <= 0)
return;
int *temp = new int[length];
mSort(Record, temp, 0, length-1);
delete[] temp;
}
参考资料:
1、www.tobebatman.com
2、数据结构,严蔚敏版