【分治】合并排序(归并排序)-HDU1106 排序

题目

HDU1106 排序

问题分析

这个题目就是把5看作空格,然后从字符串中把整数分出来,将整数按从小到大的顺序输出即可。(其实只是借这个题目来熟悉一下合并排序(归并排序),如果只是想过题的话不用这么麻烦,直接写sort就行)

算法

算法核心

本题在排序部分采用合并排序,也可以称为归并排序,所谓合并排序(归并排序)就是将一组数分为两组数量差不多的数,然后分别对两组数排序,之后再合并即可。合并排序用递归实现,递归最终是每组只有一个数,那么这个数显然是有序的,然后往上合并,得到两个数的有序序列,再往上合并直至最终整个数列都是有序的。

算法流程

前面对于把字符串中的整数分出来的部分就不多介绍了,具体看代码即可。下面来介绍一下合并排序。
b[]:暂存排序结果的数组;
a[]:待排序数组;
l:排序起始元素的下标;
r:排序中止元素的下标;
i:前面序列[l,mid]的控制变量;
j:后面序列[mid+1,r]的控制变量;
k:b[]的控制变量;
首先介绍合并函数,因为前面序列和后面序列都经过合并排序,都是有序的,所以两个序列均从头开始看即可,i和j所指元素相比较,把小的放入b[],然后控制变量后移(i或j,还有k),直至两个序列有一个全部放入b[],然后将另一个序列的剩余元素再放入b[]即可。
然后是合并排序函数,这里传入两个参数l和r,也可以传三个再加上a[],但是我把a[]定义为全局数组,所以传两个就可以。如果l<r,就把这段序列分成[l,mid]和[mid+1,r]两个序列,然后这两个序列分别进行合并排序,再合并即可。

代码实现

#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1005;

int a[maxn];//存放切割出来的数据

void Merge(int l,int mid,int r)//合并
{
    int b[maxn];
    memset(b,0,sizeof(b));
    int i=l,j=mid+1,k=0;
    while(i<=mid&&j<=r)//按序处理前面的部分
    {
        if(a[i]<a[j])
            b[k++]=a[i++];
        else
            b[k++]=a[j++];
    }
    if(i>mid)//处理后面的部分
    {
        while(j<=r)
            b[k++]=a[j++];
    }
    else
    {
        while(i<=mid)
            b[k++]=a[i++];
    }
    for(i=l,j=0; j<k; ++i,++j) //将已排序的数组并到a中
        a[i]=b[j];
}

void Mergesort(int l,int r)//合并排序
{
    if(l<r)//判断一定要有,如果没有当l=r时就会出现死循环
    {
        int mid=(l+r)/2;
        Mergesort(l,mid);
        Mergesort(mid+1,r);
        Merge(l,mid,r);
    }
}

int main()
{
    string s;
    while(cin>>s)
    {
        memset(a,0,sizeof(a));
        int i,j=0;
        bool flag=false;
        for(i=0; i<s.size(); ++i)
        {
            if(s[i]!='5')//遇到一个不是5的数表示这个数开始计算
            {
                a[j]=a[j]*10+s[i]-'0';
                flag=true;
            }
            else if(s[i]=='5'&&flag)//整数数目增加
            {
                j++;
                flag=false;
            }
            if(i==s.size()-1&&s[i]!='5')//最后一位不是5
                j++;
        }
        /*for(i=0; i<j; ++i)
            cout<<a[i]<<endl;*/
        Mergesort(0,j-1);
        cout<<a[0];
        for(i=1; i<j; ++i)
            cout<<" "<<a[i];
        cout<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值