采用分治策略
一般有三个步骤:
1、分解:将n个元素分成各含n/2个元素的子序列
2、解决:用合并排序法对两个子序列递归的排序
3、合并:合并两个已排序的子序列以得到排序结果。
在归并排序时,其长度为1时递归结束。单个元素被视为是已排序好的。
参考代码如下:
#include<iostream>
using namespace std;
#define MAX 0x7FFFFFFF //最大可能值,用于哨兵
void Merge(int *A, int low, int mid, int high)
{
if(A == NULL)return;
int n1 = mid-low+1;
int n2 = high-mid;
int *left = new int[n1+1];
int *right = new int[n2+1];
for(int i=0; i<n1; i++)
left[i] = A[i+low];
for(int j=0; j<n2; j++)
right[j] = A[j+mid+1];
//哨兵元素
left[n1] = MAX;
right[n2] = MAX;
//将left[low...mid]和right[mid+1, high]共high-low+1 个元素有序合并
int i=0,j=0;
for(int k=low; k<=high; k++)
{
if(left[i]<=right[j])
{
A[k] = left[i];
i++;
}
else
{
A[k] = right[j];
j++;
}
}
}
//归并排序
void Merge_Sort(int *A, int low, int high)
{
if(low<high)
{
int mid = (low+high)/2;
Merge_Sort(A, low, mid);
Merge_Sort(A, mid+1, high);
Merge(A, low, mid, high);
}
}
void Print(int *A, int low, int high)
{
for(int i=low; i<=high; i++)
cout<<A[i]<<" ";
cout<<endl;
}
int main()
{
int array[11] = {3, 5, 1, 9, 20, 4, 13, 6, 4, 12, 8};
int low = 0;
int high = sizeof(array)/sizeof(int)-1;
Merge_Sort(array, low, high);
Print(array, low, high);
system("pause");
return 0;
}
算法分析
(1)稳定性
归并排序是一种稳定的排序。
(2)存储结构
可用顺序存储结构。也易于在链表上实现。
(3)时间复杂度
对长度为n的文件,需进行 趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
(4)空间复杂度
需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。