分治法实现合并排序(含数据测试和分析)

1.算法思想:

①将待排序的序列一分为二

②对左右子序列排序

③子序列合并,使原序列有序

主要函数代码:

public static void mergeSort(int[ ] a, int left,  int right)  
  {
  if (left<right)
    {//至少有2个元素    
      int i=(left+right)/2;  //计算中分点
      mergeSort(a, left, i); //在第一个子集合上分类(递归)
      mergeSort(a, i+1, right); //在第二个子集合上分类(递归)
      merge(a, b, left, i, right);  //合并到数组b  
      copy(a, b, left, right);    //复制回数组a 
      } 
   } 

2.代码实现:

①归并分类算法存在的问题  :

  • 递归层次太深        

在mergeSort的执行过程中,当集合仅含有两个元素时,仍要进一步做递归调用,直至每个集合仅含有一个元素时才退出递归调用。集合含有相当少的元素时,较深层次的递归调用使得时间过多地消耗在处理递归上。    

  • 元素在数组 a 和辅助数组 b 之间的频繁移动        

        每次归并,都要首先将A中的元素移到 b 中,再由 b 复制到 a 的对应位置上。

②消去递归后:

  •  先将每两个相邻的大小为 1 的子序列归并=>对上一次归并得到的大小为 2 的子序列进行相邻归并=>……=>最后归并到一个序列,归并过程完成。
  •  通过轮流地将元素从 a 归并到b,并从b 归并到a,可以消除复制过程。
    void mergeSort(int* a,int n){
        int b [n];
        int s=1;
        while(s<n){
           mergePass(a, b, n, s); //合并到数组b
           s+=s;
           mergePass(b, a, n, s); //合并到数组a
           s+=s;
        } 
    } 
    

    功能函数:

void mergePass(int* x, int*y,int n, int s)  { //合并大小为s的相邻子数组
    int i = 0;
    while(i<n-2*s){//合并大小为s的相邻2段子数组
       merge(x, y, i, i+s-1, i+2*s-1); 
       i=i+2*s;
    }
     //剩下的元素少于2s
    if(i+s<n)
        merge(x, y, i, i+s-1, n-1);
    else//复制到y
        for(int j=i; j<n; j++)
            y[j]=x[j];
} 
void merge(int* c, int* d, int l, int m, int r)  { //合并c[l : m ] 和 c[m+1 : r] 到d[l : r]
    int i =l, j=m+1, k=l;
    while ( (i<=m) && (j<=r) )
       if ( c[ i ] <= c[ j ] )
            d[k++] = c[i++];
       else d[k++] = c[j++];
    if(i>m)
        for(int q=j;q<=r;q++)
            d[k++] = c[q];
    else
        for(int q=i;q<=m;q++)
            d[k++] = c[q];
	
}

 3.复杂度分析:

T(n)=2T(n/2)+cn

m=2 k=2 d=1,

k==m^d

T(n)=O(n^dlog_mn)=O(nlogn)

4.数据测试

运行时间与规模
规模n    10     100      100010000  100 000 200 000
耗时/s2e-0069.8e-0068.49e-0051.2261e-003 1.33002e-22.56657e-2

 

 

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hnu哈哈

请接受直女的么么哒????

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值