SCAU 8645 归并排序(非递归算法)

8645 归并排序(非递归算法)

时间限制:1000MS  代码长度限制:10KB
提交次数:2398 通过次数:1192

题型: 编程题 语言: G++;GCC

Description

用函数实现归并排序(非递归算法),并输出每趟排序的结果



 

输入格式

第一行:键盘输入待排序关键的个数n
第二行:输入n个待排序关键字,用空格分隔数据


 

输出格式

每行输出每趟排序的结果,数据之间用一个空格分隔


 

输入样例

10
5 4 8 0 9 3 2 6 7 1


 

输出样例

4 5 0 8 3 9 2 6 1 7
0 4 5 8 2 3 6 9 1 7
0 2 3 4 5 6 8 9 1 7
0 1 2 3 4 5 6 7 8 9

思路:和递归的归并排序相反,在循环次数f内(最大数据量high确定),使相邻的2^i(i=1,2,3,...每次循环+1)个数据块排序,在最后一次排序就是(1,high),排序完成。

循环次数的计算

3个数据,每次进行排序的数据块,如下

(1,2)(3,3)
(1,3)

6个数据,每次进行排序的数据块,如下

(1,2)(3,4)(5,6)
(1,4)(5,6)
(1,6)

10个数据,每次进行排序的数据块,如下

(1,2)(3,4)(5,6)(7,8)(9,10)
(1,4)(5,8)(9,10)
(1,8)(9,10)
(1,10)

……

往下写可以发现有:

第一行是数据量high,第二行是循环次数f

3456789...16
223333444

  可以看出是log2(high)向上取整的关系

int edge(int high) //计算循环次数
{
    double h=log2(high);
    high = log2(high);    
    if(high==h)    //向上取整
        return high;
    else if(high<h)
        return high+1;
}

代码实现

  1. 合并两个有序表

测试学习使用:

void Merger(int *a,int *b,int low,int mid,int high)
{
    //printf("此次low:%d,mid:%d,high:%d\n",low,mid,high);
    if(low==high) {
        b[low] = a[low];
        return;
    }
    int l=low,j=mid+1,r=high,k=low;
    while(l<=mid && j<=high)
    {

        if(a[l]>a[j] && j<=r)
            b[k++] = a[j++];
        else if(a[l]<a[j] && l<=mid)
            b[k++] = a[l++];
        else if(a[l]==a[j])
            b[k++] = a[l++];
        //printf("经过一次循环low:%d,mid:%d,high:%d\nb数组为:",low,mid,high);
        //print(b,high);
    }
    while(l<=mid) b[k++] = a[l++];
    while(j<=high) b[k++] = a[j++];
    //printf("最终low:%d,mid:%d,high:%d\nb数组为:",low,mid,high);
    //print(b,high);
    for(int i=low; i<=high; i++)
        a[i] = b[i];
    //printf("a数组为:");
    //print(a,high);
}

代码段:

void Merger(int *a,int *b,int low,int mid,int high)
{
    if(low==high) //只有一个比较的时候直接赋值到b数组
    {
        b[low] = a[low];
        return;
    }
    int l=low,j=mid+1,r=high,k=low;
    while(l<=mid && j<=high)    
    {

        if(a[l]>a[j] && j<=r)
            b[k++] = a[j++];
        else if(a[l]<a[j] && l<=mid)
            b[k++] = a[l++];
        else if(a[l]==a[j])
            b[k++] = a[l++];
    }
    while(l<=mid) b[k++] = a[l++];
    while(j<=high) b[k++] = a[j++];
    for(int i=low; i<=high; i++)  //赋值到b数组
        a[i] = b[i];
}

        2.找数据块

void m_sort(int *a,int *b,int low,int high,int n)
{
    if(low>=high)
        return;
    int f = edge(high),s,S,z,s0;
    for(int i=1; i<=f; i++)
    {
        for(s=1,S=pow(2,i);; s=S+1,S=S+i*2)
        {
            if(s>high)
                break;
            if(S>high)
            {
                if(i==f&&z!=0)
                {
                    S = high;
                    //printf("s:%d s0:%d S:%d i:%d\n",s,s0,S,i);
                    //printf("排序前是:");
                    //print(b,S);
                    Merger(a,b,s,s0,S);
                    //printf("排序后是:");
                    //print(b,S);
                    break;
                }
                z=0;
                S = high;
                //printf("s:%d S:%d i:%d\n",s,S,i);
                //printf("排序前是:");
                //print(b,S);
                Merger(a,b,s,(s+S)/2,S);
                //printf("排序后是:");
                //print(b,S);
                s0 = s-1;
                z++;
                break;
            }
            //printf("s:%d S:%d i:%d\n",s,S,i);
            //printf("排序前是:");
            //print(b,S);
            Merger(a,b,s,(s+S)/2,S);
            //printf("排序后是:");
            //print(b,S);
        }
        print(b,n);
    }
}
void m_sort(int *a,int *b,int low,int high,int n)
{
    if(low>=high)
        return;
    int f = edge(high),s,S,z,s0;
    for(int i=1; i<=f; i++)
    {
        for(s=1,S=pow(2,i);; s=S+1,S=S+i*2)
        {
            if(s>high)
                break;
            if(S>high)
            {
                if(i==f&&z!=0)
                {
                    S = high;
                    Merger(a,b,s,s0,S);
                    break;
                }
                z=0;
                S = high;
                Merger(a,b,s,(s+S)/2,S);
                s0 = s-1;
                z++;
                break;
            }
            Merger(a,b,s,(s+S)/2,S);
        }
        print(b,n);
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值