并归排序
1 基本原理
1 核心思想:归并排序,是创建在归并操作上的一种有效的排序算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。
2 算法分析:
- 通过分治法将长度为n的序列划分为n个长度为1的子序列。
- 进行两两归并比较,得到 n/2 个长度为 2 的有序子序列
- 重复第 2 步,直到所有子序列归并成一个长度为 n 的有序序列。
2 实例说明
如上图所示,以一组数据{2,4,7,5,8,1,3,6} 为例,进行并归排序的算法演示:
- 将原数组通过二分法不断分解,直至划分为8个长度为1是子数组。
- 将8个子数组两两进行并归排序,合成4个有序的子数组。
- 重复第2步操作,直至合并成一个长度为8的有序数组,排序完成。
3 代码实现
// 并归排序(C++)
void Merge(vector<int> &a, int left, int mid, int right)
{
int len1 = mid - left + 1;
int len2 = right - mid;
int *l1 = new int[len1];
int *l2 = new int[len2];
for (int i = 0; i<len1; ++i)
{
l1[i] = a[left + i];
}
for (int j = 0; j<len2; ++j)
{
l2[j] = a[j + mid + 1];
}
//比较两个序列
int i = 0, j = 0;
while (i<len1 && j<len2)
{
if (l1[i]<l2[j])
{
a[left++] = l1[i++];
}
else
{
a[left++] = l2[j++];
}
}
//两序列剩余部分分别放于尾部
while (i<len1)
{
a[left++] = l1[i++];
}
while (j<len2)
{
a[left++] = l2[j++];
}
delete[]l1;
delete[]l2;
}
void MergeSort(vector<int> &a, int left, int right)
{
if (left<right)
{
int mid = (left + right) / 2; //分解
MergeSort(a, left, mid);
MergeSort(a, mid + 1, right);
Merge(a, left, mid, right); //合并
//排序过程输出
for (auto x : a)
cout << x << " ";
cout << endl;
}
}
4 性能分析
- 1 时间复杂度:
归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要 logN 步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN),故时间复杂度为O(nlogn)。 - 2 空间复杂度:
并归排序过程中,需要一个辅助空间来暂存两有序子文件归并的结果,因此空间复杂度为O(n)。 - 3 算法稳定性:
选择排序是稳定的算法,在分解和并归过程中元素相对顺序未发生改变。