设为首页 加入收藏

TOP

算法---归并排序(Merge Sort)---多版本对比
2015-02-02 14:43:38 来源: 作者: 【 】 浏览:38
Tags:算法 --- 归并 排序 Merge Sort 版本 对比

归并排序是一种利用“分治”手段来实现的排序方法,其通过二分将数组分为若干个有序的子数组,然后再将这些子数组合并到一起组成一个新的数组。


算法的具体实现:


void sort::merge_sort(int* a, const int low, const int high)
{
?if(low>= high)
? return;
?int mid = (low+high)/2;
?merge_sort(a,low,mid);
?merge_sort(a,mid+1,high);
?merge(a,low,mid,high);
}


上述实现可以看出,此算法通过递归将数组分为若干个有序的小数组,然后再使用merge方法将这些小数组进行合并,从而完成数组的排序。


merge方法的实现


void sort::merge(int*a ,const int low,const int mid, const int high)
{
?if(a[mid]<=a[mid+1])
? return ;
?int* copy_a = new int[high-low+1];
?for(int i=low; i<=high; i++)
? copy_a[i-low] = a[i];
?int i=low;
?int j=mid+1;
?for(int k=low; k<=high; k++)
?{
? if(i>mid)
? {
? ?a[k] = copy_a[j-low];
? ?j++;
? }
? else if(j>high)
? {
? ?a[k] = copy_a[i-low];
? ?i++;
? }
? else if(copy_a[i-low]>copy_a[j-low])
? {
? ?a[k] = copy_a[j-low];
? ?j++;
? }
? else
? {
? ?a[k] = copy_a[i-low];
? ?i++;
? }
?}
?delete[] copy_a;
}


上述实现可以看出,其实就是将两个有序的数组合并到一个新的数组中而已。


算法的时间复杂度分析,假设有N个数,使用归并排序所需的时间为T(N),则从算法的实现可以看出,对N个数排序,需要先分别对左右两边的N/2个数排序,时间为2T(N/2),然后再将排序的两个数组合并,所需时间为N,因此可得T(N) = 2*T(N/2)+N,计算可得T(N)=NlogN。


上述算法可有改进的地方。显然是有的。


首先,如果使用归并排序来排序较小的数组的话,其算法性能没有之前所说的插入排序好(插入排序算法实现),为此可以设定一个阈值,再使用归并排序的过程中如果子数组的元素个数小于这个阈值时,使用插入排序来对相应的子数组进行排序。


算法实现:


void sort::merge_sort_update1(int* a, const int low, const int high)
{
?if((high-low + 1) < N)
?{
? for(int i=low+1; i<=high; i++)
? {
? ?int j=i;
? ?int temp = a[i];
? ?for(; j>low && temp < a[j-1]; j--)
? ?{
? ? a[j] = a[j-1];
? ?}
? ?a[j] = temp;
? }
? return;
?}
?int mid = (low + high)/2;
?merge_sort_update1(a,low,mid);
?merge_sort_update1(a,mid+1,high);
?merge(a,low,mid,high);
}


上述算法改进之后性能上比原来的归并排序稍好,但是算法的时间复杂度仍然为O(NlogN)。


能否再进一步改进呢?


观察发现,归并排序始终使用一个备份数组来存储排序后的元素,然后再将排序后的元素复制到原来的数组中。在数组新建的过程中将会花费大量的时间。为此可以在这个方面改进一下。可以使用一个实现建好的数组,然后只需使用赋值运算即可,避免了不必要的数组的新建与删除,从而加快了算法的执行速度。


算法实现:


void sort::merge_sort_update2(int* a, const int low, const int high, int* copy_a)
{
?if(low>=high)
? return;
?int mid = (low+high)/2;
?merge_sort_update2(a,low,mid,copy_a);
?merge_sort_update2(a,mid+1,high,copy_a);
?merge_update2(a,low,mid,high,copy_a);
?for(int i=low; i<=high; i++)
? copy_a[i] = a[i];
}


void sort::merge_update2(int*a ,const int low,const int mid, const int high,const int * copy_a)
{
?if(a[mid] <= a[mid+1])
? return;
?int i=low;
?int j=mid+1;
?for(int k=low; k<=high; k++)
?{
? if(i>mid)
? ?a[k] = copy_a[j++];
? else if(j>high)
? ?a[k] = copy_a[i++];
? else if(copy_a[i] > copy_a[j])
? ?a[k] = copy_a[j++];
? else
? ?a[k] = copy_a[i++];
?}
}


上述仅仅是自己在学习归并排序过程中实现的一些想法,如有不足之处还请多多指出,欢迎讨论。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇算法---快速排序(quick sort) 下一篇算法----插入排序(insert sort)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: