归并排序理论上时间复杂度只有O(NlogN),但是其中存在过多临时内存分配和copy操作而不适用于内存排序,却是外部排序的基本思路。下面是我的实现:
#include<iostream> #include<algorithm> #include<cstring> using namespace std; int g=0; /*a,b is input array * c is output array * size of c is na+nb */ template<typename T> void merge(T a[],int na,T b[],int nb,T c[]) { T* pa=a; T* pb=b; T* pt= new T[na+nb]; int i=0,j=0,k=0; while(i<na+nb) { while(j<na && k<nb && pa[j]<=pb[k]) { pt[i++]=pa[j++]; } while(j<na && k<nb && pb[k]<=pa[j]) { pt[i++]=pb[k++]; } if(j==na){ while(k<nb) pt[i++]=pb[k++]; break; } if(k==nb){ while(j<na) pt[i++]=pa[j++]; break; } } cout<<"merge"<<g++<<":"; for(int i=0;i<na+nb;i++) { c[i]=pt[i]; cout<<c[i]<<' '; } cout<<endl; delete []pt; } template<typename T> void mergesort(T a[],int n) { if(n<=1)return; int m=n/2; mergesort(a,m); mergesort(a+m,n-m); merge(a,m,a+m,n-m,a); } template<typename T> void show(T a[],int n) { for(int i=0;i<n;++i) { cout<<a[i]<<' '; } cout<<endl; } int main() { int l1[]={2,7,9,12}; int l2[]={3,6,8,11}; int l3[8]; merge(l1,4,l2,4,l3); int a[]={9,3,6,2,7,5,8,0,4,1}; mergesort(a,10); show(a,10); return 0; }
一些注意要点:
1.归并排序是归并算法的一个应用,所以要先实现归并算法,排序的时候先递归后操作。(如果递归算法是在第一层处理数据然后处理分支数据就是【先操作后递归】,如果是先分支从最后的分支开始处理数据向第一层合并,就是【先递归后操作】)。
2.尽量不要递归申请内存,那样会申请大量临时内存,这些内存的数据要保存又要大量的copy操作。
3.使用链表排序就不用临时分配内存也不用频繁copy。
4.循环嵌套的逻辑一次不一定写正确,先用while嵌套,逻辑更清晰。