题目
问题分析
这个题目就是把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;
}