基本思想
归并排序使用的是分治法
分治法的基本思想是将原问题分解为规模较小但类似于原问题的子问题, 递归地求解这些子问题,然后合并这些子问题的解来建立原问题的解。
分治模式在每层递归都有3个步骤
1.分解
2.解决
3.合并
归并排序对应的有下面3个步骤
1.分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列
2.解决:使用归并排序递归地排序两个子序列
3.合并:合并两个排序的子序列以产生已排序的答案
归并算法的关键操作是将两个已排序序列的合并。
我们拿扑克牌当例子:假设桌上有两堆牌已排序的面朝上的牌(最小的在上面),我们希望把这两堆牌合并成单一的排序好的牌。
我们的基本步骤是从两堆牌的牌顶上面拿出较小的一张,放到输出堆,重复这个步骤(如果一个堆为空,则可以当它面朝上的牌为∞)就可以达到目的。
伪代码
合并代码:将排序好的两个数组A[p...q]和A[q+1...r]合并成一个排序好的数组
MERGE(A,p,q,r) n1=q-p+1 n2=r-q let L[1...n1+1] and R[1...n2+1] be a new arrays for i=1 to n1 L[i]=A[p+i-1] for j=1 to n2 R[j]=A[p+j] L[n1+1]=max R[n2+1]=max i=1 j=1 for k=p to r if L[i]<=R[j] A[k]=L[i] i=i+1 else A[k]=R[j] j=j+1
我们把过程MERGE作为归并排序算法中的一个子程序来用。递归的把问题分解成两个子问题,然后合并子问题得到原问题的解
MERGE-SORT(A,p,r) if p<r q=(p+r)/2 向下取整 MERGE-SORT(A,p,q) MERGE-SORT(A,q+1,r) MERGE(A,p,q,r)
实现和测试代码
#include <iostream>
#include <limits>
using namespace std;
void merge(int arr[],int p,int q,int r)
{
int n1=q-p+1;
int n2=r-q;
int *L=new int[n1+2];
int *R=new int[n2+2];
for(int i=1;i<=n1;++i)
L[i]=arr[p+i-1];
for(int j=1;j<=n2;++j)
R[j]=arr[q+j];
L[n1+1]=numeric_limits<int>::max();
R[n2+1]=numeric_limits<int>::max();
int i=1,j=1;
for(int k=p;k<=r;++k)
{
if(L[i]<=R[j])
arr[k]=L[i++];
else
arr[k]=R[j++];
}
delete[] L;
delete[] R;
}
void merge_sort(int arr[],int p,int r)
{
if(p<r)
{
int q=(p+r)/2;
merge_sort(arr,p,q);
merge_sort(arr,q+1,r);
merge(arr,p,q,r);
}
}
int main()
{
int arr[]={0,5,2,4,7,1,3,2,6};
merge_sort(arr,1,8);
for(int i=1;i<=8;++i)
cout<<arr[i]<<' ';
cout<<endl;
system("pause");
}