归并操作:
归并操作,也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法,平均时间复杂度为O(nlogn)。 归并排序的实现分为递归实现与非递归(迭代)实现。
如 设有数列{6,202,100,301,38,8,1}
初始状态:6,202,100,301,38,8,1
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
总的比较次数为:3+4+4=11;
逆序数为14;
算法思路:
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾,将另一序列剩下的所有元素直复制到合并序列尾。
代码如下(C++):
#include <iostream>
#define MAXSIZE 6
using namespace std;
void Merge(int A[], int left, int mid, int right)// 合并两个已排好序的数组A[left...mid]和A[mid+1...right]
{
int len = right - left + 1;
int *temp = new int[len]; // 辅助空间O(n)
int index = 0;
int i = left; // 前一数组的起始元素
int j = mid + 1; // 后一数组的起始元素
while (i <= mid && j <= right)
{
temp[index++] = A[i] <= A[j] ? A[i++] : A[j++]; // 带等号保证归并排序的稳定性
}
while (i <= mid)
{
temp[index++] = A[i++];
}
while (j <= right)
{
temp[index++] = A[j++];
}
for (int k = 0; k < len; k++)
{
A[left++] = temp[k];
}
}
void MergeSortRecursion(int A[], int left, int right) // 递归实现的归并排序(自顶向下)
{
if (left == right) // 当待排序的序列长度为1时,递归开始回溯,进行merge操作
return;
int mid = (left + right) / 2;
MergeSortRecursion(A, left, mid);
MergeSortRecursion(A, mid + 1, right);
Merge(A, left, mid, right);
}
void MergeSortIteration(int A[], int len) // 非递归(迭代)实现的归并排序(自底向上)
{
int left, mid, right; // 子数组索引,前一个为A[left...mid],后一个子数组为A[mid+1...right]
for (int i = 1; i < len; i *= 2) // 子数组的大小i初始为1,每轮翻倍
{
left = 0;
while (left + i < len) // 后一个子数组存在(需要归并)
{
mid = left + i - 1;
right = mid + i < len ? mid + i : len - 1;// 后一个子数组大小可能不够
Merge(A, left, mid, right);
left = right + 1; // 前一个子数组索引向后移动
}
}
}
int main()
{
int i,j;
int A1[MAXSIZE]; // 从小到大归并排序
int A2[MAXSIZE] ;
int n1 = sizeof(A1) / sizeof(int);
int n2 = sizeof(A2) / sizeof(int);
cout<<"请输入MAXSIZE个数字(递归实现): ";
for(i=0;i<MAXSIZE ;i++)
cin>>A1[i];
cout<<"请输入MAXSIZE个数字(非递归实现):";
for(j=0;j<MAXSIZE ;j++)
cin>>A2[j];
MergeSortRecursion(A1, 0, n1 - 1); // 递归实现
MergeSortIteration(A2, n2); // 非递归实现
cout<<"递归实现的归并排序结果:";
for (int i = 0; i < n1; i++)
{
cout<<A1[i]<<" ";
}
cout<<endl;
cout<<"非递归实现的归并排序结果:";
for (int i = 0; i < n2; i++)
{
cout<<A2[i]<<" ";
}
cout<<endl;
return 0;
}