摘自算法《竞赛入门经典训练指南》
例题 年龄排序(Age Sort,UVa 11462)
给定若干居民的年龄(都是1~100之间的整数),把它们按照从小到大的顺序输出。
【输入】
输入包含多组测试用例。每组数据的第一行为整数n(0<n<=2 000 000),即居民总数;下一行包含n个不小于1、不大于100的整数,即各居民的年龄。输入结束标志为n=0。
输入文件约有25mb,而内存限制只有2mb。
【输出】
对于每组数据,按照从小到大的顺序输出各居民的年龄,相邻年龄用单个空格隔开。
【分析】
由于数据太大,内存限制吃紧(甚至都不能把它们全读入内存),因此无法使用快速排序方法。但整数范围很小,可以用计数排序方法。下面是程序代码。
#include <cstdio> #include <cstring> int main(){ int n,x,c[101]; while(scanf("%d",&n)==1 && n){ memset(c,0,sizeof(c)); for(int i=0;i<n;i++){ scanf("%d",&x); c[x]++; } int first=1; for(int i=1;i<=100;i++){ for(int j=0;j<c[i];++j){ if(!first)printf(" "); first=0; printf("%d",i ); } } printf("\n"); } }
如果还要精益求精,可以优化输入输出,进一步降低运行时间。程序如下。
#include <cstdio> #include <cstring> #include <cctype> inline int readint(){ char c=getchar(); while(!isdigit(c))c=getchar(); int x=0; while(isdigit(c)){ x=x*10+c-‘0‘; c=getchar(); } return x;//Warning: x > 0; } int buf[10]; inline void writeint(int i){ int p=0; if(i==0)p++; else while(i){ buf[p++]=i%10; i/=10; } for(int j=p-1;j>=0;j--)putchar(‘0‘+buf[j]);//逆序输出 } int main(){ int n,x,c[101]; while(n=readint()){ memset(c,0,sizeof c); for(int i=0;i<n;++i)c[readint()]++; int first=1; for(int i=0;i<=100;++i){ for(int j=0;j<c[i];++j){ if(!first)putchar(‘ ‘); first=0; writeint(i); } } putchar(‘\n‘); } return 0; }
上述优化使得程序运行时间缩短了约2/3。一般情况下,当输入输出数据量很大时,应尽量用scanf和printf函数;如果时间效率还不够高,应逐字符输入输出,就像上面的readint和writeint函数。不管怎样,在确信I/O时间成为整个程序性能瓶颈之前,不要盲目优化。测试方法也很简单:输入之后不执行主算法,直接输出一个任意的结果,看运行时间是否过长。
时间: 2024-12-29 11:22:09