归并排序

来源:互联网 发布:幽默淘宝店铺公告范文 编辑:程序博客网 时间:2024/05/22 18:18

归并排序(MergeSort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。





归并排序,它采取分而治之(Divide-and-Conquer)的策略,时间复杂度是O(N*lgN)。

归并排序的步骤如下:

1. Divide: 把长度为n的输入序列分成两个长度为n/2的子序列。

2. Conquer: 对这两个子序列分别采用归并排序。

3. Combine: 将两个排序好的子序列合并成一个最终的排序序列。

在描述归并排序的步骤时又调用了归并排序本身,可见这是一个递归的过程。


下面过程来分析,见下图:




代码实现:

void _MergeSort(int* a,int* tmp,int left,int right){if(left >= right)return;int mid=left+((right-left)>>1);int begin1=left,end1=mid;int begin2=mid+1,end2=right;if(left < mid)      //left=mid时,单个元素不进行分割_MergeSort(a,tmp,left,mid);if(mid < right)_MergeSort(a,tmp,mid+1,right);int index=left;//进行归并while(begin1 <= end1 && begin2 <= end2){if(a[begin1] < a[begin2])tmp[index++]=a[begin1++];elsetmp[index++]=a[begin2++];}while(begin1 <= end1)   //一段为空,一段不为空的情况单独考虑{tmp[index++]=a[begin1++];}while(begin2 <= end2)  {tmp[index++]=a[begin2++];}for(int i=left;i<=right;++i){a[i]=tmp[i];}}void MergeSort(int* a,int begin,int end){assert(a);int* tmp=new int[end-begin+1];assert(tmp);_MergeSort(a,tmp,begin,end);delete[] tmp;}

归并排序算法改进:

可利用插入排序优化归并排序,

在归并中利用插入排序不仅可以减少递归次数,还可以减少内存分配次数(针对于原始版本)。

尽管归并排序最坏情况运行时间为o(nlgn),插入排序的最坏运行时间为o(n^2),但是插入排序的常数因子使得它在n较小时,运行要更快一些。因此,在合并排序算法中,当子问题足够小时(子区间元素个数小于13),采用插入排序就比较合适了。然后,再用标准的合并机制将它们合并起来。

 

void InsertSort(int* arr,size_t sz){assert(arr);for(int index=1;index<sz;++index)  //先默认下标为0的元素有序{int pos=index-1;int tmp=arr[index];while(pos>=0 && tmp < arr[pos]){std::swap(arr[pos],arr[pos+1]);--pos;}arr[pos+1]=tmp;}}void _MergeSort(int* a,int* tmp,int left,int right){if(left >= right)return;int mid=left+((right-left)>>1);int begin1=left,end1=mid;int begin2=mid+1,end2=right;if(left < mid)      //left=mid时,单个元素不进行分割{if(right-left >13)_MergeSort(a,tmp,left,mid);elseInsertSort(a+left,right-left+1);}if(mid+1 < right)     { if(right-mid-1 >13)_MergeSort(a,tmp,right,mid);elseInsertSort(a+mid+1,right-mid);   //[mid+1,right]所以元素个数为right-mid}int index=left;//进行归并while(begin1 <= end1 && begin2 <= end2){if(a[begin1] < a[begin2])tmp[index++]=a[begin1++];elsetmp[index++]=a[begin2++];}while(begin1 <= end1)   //一段为空,一段不为空的情况单独考虑{tmp[index++]=a[begin1++];}while(begin2 <= end2)  {tmp[index++]=a[begin2++];}for(int i=left;i<=right;++i){a[i]=tmp[i];}}void MergeSort(int* a,int begin,int end){assert(a);int* tmp=new int[end-begin+1];assert(tmp);_MergeSort(a,tmp,begin,end);delete[] tmp;}


比较排序算法就先介绍到此,下面看一下它们之间的区别:




0 0