为什么会有如此多的排序方法呢,我们常使用的有冒泡、选择、快速排序,希尔排序等等。这是因为每一种排序方法有其特定的使用范围,尤其是对时间和空间复杂度要求高的算法中,很显然像冒泡这类的高复杂度的算法就无法胜任。对付此类问题则需要使用到高等排序方法。而归并排序就是其中之一。
归并排序理解其实也非常简单,就是将数组分割为包含n/2个元素局部数组,对每个数组继续执行归并排序。并通过Merge(合并)将两个已排序完毕的数组“整合”到一个数组。
在该算法中,最重要的就是合并两个已经排好序的数组,它是整个算法的基础。我们要将包含n1个元素的数组L和包含n2个元素的数组R合并到A中。若假设数组L和R都已按升序排好,我们要做的就是将L和R中的元素赋值到A中,并同时保证A中的元素升序排列。
通常,为了简化合并(merge)的实现,我们在L和R的末尾分别插入一个大于所有元素的标记。在比较L和R的过程中,势必会遇到与标记相比较的情况,只要将标记设的足够大,且比较次数限制在(n2+n1)之内,就可以防止两个标记做比较,又可防止i、j分别超过n1、n2。
下面给出该归并排序的伪代码:
merge(A,left,mid,right)
n1=mid-left
n2=right-mid
生成L[0...n1],R[0...n2]
for i=0 to n1-1
L[i]=A[left+i]
for i=0 to n2-1
R[i]=A[mid+i]
L[n1]=INFTY
L[n2]=INFTY
i=0
j=0
for k=left to right-1
if L[i]<=R[i]
A[k]=L[i]
i=i+1
else
A[k]=R[j]
j=j+1
//局部数组只剩一个元素时,不做处理直接结束,否则计算局部数组中间位置mid,
//将left到mid视为前半部分,mid 到right视为后半部分。再进行MergeSort(分割)
mergeSort(A,left,right) //分割数组
if left+1 < right
mid=(left+right)/2;
mergeSort(A,left,mid)
mergeSort(A,mid,right)
mergeSort(A,left,mid,right)
//mergeSort的三个参数分为为数组A以及表示其局部数组范围的变量left,right。left指局部数组的
//开头,right指局部数组末尾+1的位置。
一般来说,归并排序n个数据会分为log2n层。由于每层执行merge的总复杂为O(n),因此归并排序的整体复杂度为O(nlogn)。
此外,归并排序包含不相邻元素之间的比较,但并不会直接交换。在合并数组时,若遇到相同元素,只需保证前半部分数组由于后半部分数组,相同元素的顺序就不会改变。因此,其是一种稳定的排序算法。但在处理过程中,除用于保存输入数据的数组之外,还需要临时占用一部分内存空间.
下面完整代码是归并排序的例子:
#include <iostream>
using namespace std;
#define MAX 500000
#define SENTINEL 2000000000
int L[MAX/2+2],R[MAX/2+2];
int cnt;
void merge(int A[],int n,int left,int mid,int right){
int n1=mid-left;
int n2=right-mid;
for(int i=0;i<n1;i++) L[i]=A[left+i];
for(int i=0;i<n2;i++) R[i]=A[mid+i];
L[n1]=R[n2]=SENTINEL;
int i=0,j=0;
for(int k=left;k<right;k++){
cnt++;
if(L[i]<=R[j]){
A[k]=L[i++];
}
else{
A[k]=R[j++];
}
}
}
void mergeSort(int A[],int n,int left,int right){
if(left+1<right){
int mid=(left+right)/2;
mergeSort(A,n,left,mid);
mergeSort(A,n,mid,right);
merge(A,n,left,mid,right);
}
}
int main(){
int A[MAX],n;
cnt=0;
cin>>n;
for(int i=0;i<n;i++) cin>>A[i];
mergeSort(A,n,0,n);
for(int i=0;i<n;i++){
if(i)std::cout << " ";
cout<<A[i];
}
cout<<endl;
cout<<cnt<<endl;
return 0;
}
到此,归并排序内容基本介绍完毕。