归并排序的C++实现(大众版)

来源:互联网 发布:超星泛雅网络教学平台 编辑:程序博客网 时间:2024/06/04 08:06

归并排序的C++实现(大众版)

 

        归并排序,是利用分治策略而成的一个典型应用。它将n个元素分成各含n/2个元素的子序列;然后再用合并排序法对两个子序列递归地排序;最后合并两个已排序的子序列,以得到排序结果。在对子序列排序时,对于单个元素,被视为已序,也就可以认为递归结束。其运行时间为Θ(nlogn)

        归并排序的分解过程中,MERGE-SORT伪代码如下:

MERGE-SORT(A,p,r)if p<r   then q=[(p+r)/2]        MERGE-SORT(A,p,q)        MERGE-SORT(A,q+1,r)        MERGE(A,p,q,r)

        在一段序列中,先利用左端位置p和右端位置r取得中间位置q,然后对一分为二的序列进行多次拆分直到只剩1个元素,最后再用MERGE对已序区间进行合并。
        而在归并排序的合并过程中,MERGE伪代码如下:

MERGE(A,p,q,r)n1=q-p+1       //左段子序列的起始位置n2=r-q         //右段子序列的起始位置create arrays L[1..n1+1]and R[1..n2+1]for i=1 to n1    L[i]=A[p+i-1]for j=1 to n2    R[i]=A[q+j]L[n1+1]=∞R[n2+1]=∞i=1j=1for k=p to r    if (L[i]<=R[j])       A[k]=L[i]       i=i+1    else        A[k]=R[j]        j=j+1

        在合并两个已序子序列时,先用辅助序列L和R将A中元素分开存储,然后再通过比较两个子序列所指向的哨兵元素,选更小的放入主序列A中;最后当某一个子序列都完全放入主序列A后,再将另一个子序列的剩余所有元素一起放入主序列A中。伪代码中的正无穷符号,就是为了标记序列尾的。

        最后贡献出归并排序的C++实现,与伪代码相比做了一些改变,不过其主体思想如出一辙:

#include<iostream>#include<vector>#include<algorithm>#include<iterator>template<typename T>void mymerge(std::vector<T>& a,int left,int middle,int right);template<typename T>void mergesort(std::vector<T>& a,int left,int right);template<typename T>void print(const std::vector<T>& a);template<typename T>void mergesort(std::vector<T>& a,int left,int right){     int middle;     if (left<right)         {        middle=(int)((left+right)/2);                   mergesort(a,left,middle);              //递归拆分左半边数组         mergesort(a,middle+1,right);           //递归拆分右半边数组         mymerge(a,left,middle,right);          //合并数组      }}template<typename T>void mymerge(std::vector<T>& a,int left,int middle,int right){     int n1,n2,i,j,k;       n1=middle-left+1;     n2=right-middle;     T* Left=new T[n1];     T* Right=new T[n2];     for (i=0;i<n1;i++)         Left[i]=a[left+i];     for (j=0;j<n2;j++)         Right[j]=a[middle+1+j];     i=j=0;     k=left;     while (i<n1 && j<n2)     //将数组元素值两两比较,并合并到a数组      {           if (Left[i]<=Right[j])                    a[k++]=Left[i++];           else               a[k++]=Right[j++];     }     for (;i<n1;i++)   //如果左数组有元素剩余,则将剩余元素合并到a数组          a[k++]=Left[i];     for (;j<n2;j++)   //如果右数组有元素剩余,则将剩余元素合并到a数组          a[k++]=Right[j];     delete []Right;     delete []Left;}template<typename T>void print(const std::vector<T>& a){     std::ostream_iterator<T>out(std::cout," ");     copy(a.begin(),a.end(),out);     std::cout<<std::endl;}int main(){std::vector<int> a;a.push_back(5);a.push_back(2);a.push_back(0);a.push_back(1);a.push_back(3);a.push_back(7);a.push_back(9);a.push_back(4);a.push_back(8);a.push_back(6);mergesort(a,0,a.size()-1);print(a);      //输出最后归并排序的结果 std::cin.sync();std::cin.get();}



 

 

参考文献:

1.《算法导论》2nd   Thomas H.Cormen , Charles E.Leiserson , Ronald L.Rivest , Cliford Stein 著,潘金贵、顾铁成、李成法、叶懋译
2.《数据结构与算法分析 C++描述》 第3版  Mark Allen Weiss著,张怀勇等译
3.《C++标准模板库 -自修教程及参考手册-》  Nicolai M.Josuttis著,侯捷/孟岩译