归并排序
归并:将两个或两个以上的有序表组合成一个新有序表。
- 排序过程:
初始序列看成n个有序子序列,每个子序列长度为1;
两两合并,得到n/2个长度为2或1的有序子序列;
再两两合并,重复直至得到一个长度为n的有序序列为止。 - 例子
- 代码实现:
代码可结合上面例子进行理解。
#include<iostream>
using namespace std;
//共同部分——将两个有序序列合并为一个有序序列
void Merge(int list[], int low, int m, int high)
{
int temp[8];//暂存数组
int i = low;
int j = m + 1;
int k = low;
while (i <= m && j <= high)
{
if (list[i] < list[j])
temp[k] = list[i++];
else
temp[k] = list[j++];
k++;
}
while (i <= m)
{
temp[k] = list[i++];
k++;
}
while (j <= high)
{
temp[k] = list[j++];
k++;
}
for (int i = low; i <= high; i++)
list[i] = temp[i];
}
//递归实现——begin
void mergeSort(int list[], int low, int high)
{
if (low < high)
{
int mid = (low + high) / 2;
mergeSort(list, low, mid); //将nums[low ~mid]归并为有序的 nums[low ~mid]
mergeSort(list, mid + 1, high); //将nums[mid + 1 ~high]归并为有序的 nums[mid + 1 ~high]
Merge(list, low, mid, high);//将有序的 nums[low ~ m] 和 nums[m+1 ~ high] 归并到 nums[low ~ high]
}
}
//递归实现——end
//迭代实现——begin
//sonLen为子序列长度,为1,2,4,……,len为数组长度
void mSort2(int list[], int sonLen, int len)
{
int low = 0;
int high = low + 2 * sonLen - 1;
while (high < len)//前面的子序列
{
int mid = (low + high) / 2;
Merge(list, low, mid, high);
low = low + 2 * sonLen;
high = high + 2 * sonLen;
}
if (low < len - sonLen + 1)//将剩下不规则的子序列合并起来
Merge(list, low, low + sonLen - 1, len - 1);
}
void mergeSort2(int list[],int len)
{
int sonLen = 1;//子序列的归并长度从1开始迭代,之后依次乘2
while (sonLen < len)
{
mSort2(list, sonLen,len);
sonLen *= 2;
}
}
//迭代实现——end
int main()
{
int list[8] = { 49,38,65,97,76,13,27,49 };
int n = sizeof(list)/sizeof(int);
mergeSort(list, 0, n - 1);//递归实现
mergeSort2(list,n);//迭代实现
for (int i = 0; i < n - 1; i++)
cout << list[i] << '\t';
cout << endl;
system("pause");
}
参考代码:github源码
- 算法分析
在迭代的归并排序算法中,时间复杂度为 O(nlogn),空间复杂度为 O(n)。
在递归的归并排序算法中,时间复杂度为 O(nlogn),空间复杂度为 O(n+logn)。
归并排序是一种稳定的排序算法。