方法1:重载运算符。
方法2:重写cmp函数。
关于strcmp函数(C/C++函数):
设这两个字符串为str1,str2,
若str1=str2,则返回零;
若str1<str2,则返回负数;
若str1>str2,则返回正数。
大整数排序
对N个长度最长可达到1000的数进行排序。
输入描述
输入第一行为一个整数N,(1<=N<=100)。
接下来的N行每行有一个数,数的长度范围为1<=len<=1000。
每个数都是一个正数,并且保证不包含前缀零。
输出描述
可能有多组测试数据,对于每组数据,将给出的N个数从小到大进行排序,输出排序后的结果,每个数占一行。
输入
3
11111111111111111111111111111
2222222222222222222222222222222222
33333333
输出
33333333
11111111111111111111111111111
2222222222222222222222222222222222
//大整数排序
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct Str{
string s;
int len;
bool operator < (const Str &a)const{
if(len!=a.len) return len<a.len;
else return strcmp(s.c_str(),a.s.c_str())<0;
}
};
Str s[101];
int main(void){
int N;
while(cin>>N){
string str;
for(int i=0;i<N;i++)
{
cin>>str;
s[i].s=str;
s[i].len=str.length();
}
sort(s,s+N);
for(int i=0;i<N;i++){
cout<<s[i].s<<endl;
}
}
return 0;
}
//大整数排序
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(string a,string b)
{
if(a.length()!=b.length())
return a.length()<b.length();
else
return a<b;//string类可以字典序直接比较
}
int main()
{
int N;
while(cin>>N)
{
getchar();
string a[101];
for(int i=0;i<N;getline(cin,a[i++]));
sort(a,a+N,cmp);
for(int i=0;i<N;cout<<a[i++]<<endl);
}
}
Excel排序
题目描述
Excel可以对一组纪录按任意指定列排序。现请你编写程序实现类似功能。 对每个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在 N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3 时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。
输入描述
测试输入包含若干测试用例。每个测试用例的第1行包含两个整数 N (N<=100000) 和 C,其中 N 是纪录的条数,C 是指定排序的列号。以下有N行,每行包含一条学生纪录。每条学生纪录由学号(6位数字,同组测试中没有重复的学号)、姓名(不超过8位且不包含空格的字符串)、成绩(闭区间[0, 100]内的整数)组成,每个项目间用1个空格隔开。当读到 N=0 时,全部输入结束,相应的结果不要输出。
输出描述
对每个测试用例,首先输出1行“Case:”。随后在 N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3
时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。
输入
3 1
000007 James 85
000010 Amy 90
000001 Zoe 60
输出
Case:
000001 Zoe 60
000007 James 85
000010 Amy 90
//EXCEL排序
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Record{
char id[7];//注意学号是6位数,如果数组设定太小了,不能存储‘\0’终止符号
char name[9];
int grade;
};
bool cmp1(Record a,Record b){
return strcmp(a.id,b.id)<0;
}
bool cmp2(Record a,Record b){
if(a.name!=b.name) return strcmp(a.name,b.name)<0;
else return strcmp(a.id,b.id)<0;
}
bool cmp3(Record a,Record b){
if(a.grade!=b.grade) return a.grade<b.grade;
else return strcmp(a.id,b.id)<0;
}
Record r[100001];
void action(int type,Record r[],int n){
switch(type){
case 1:sort(r,r+n,cmp1);break;
case 2:sort(r,r+n,cmp2);break;
case 3:sort(r,r+n,cmp3);break;
}
}
int main(void)
{
int cases=0;
int N;
while(scanf("%d",&N)!=EOF){
cases++;
if(N==0) break;
int type;
cin>>type;
for(int i=0;i<N;i++){
scanf("%s%s%d",&r[i].id,&r[i].name,&r[i].grade);
}
action(type,r,N);
printf("Case:\n",cases);
for(int i=0;i<N;i++){
printf("%s %s %d\n",r[i].id,r[i].name,r[i].grade);
}
}
return 0;
}
开门人和关门人
题目描述
每天第一个到机房的人要把门打开,最后一个离开的人要把门关好。现有一堆杂乱的机房签到、签离记录,请根据记录找出当天开门和关门的人。
输入描述
每天的记录在第一行给出记录的条目数M (M > 0 ),下面是M行,每行的格式为 证件号码 签到时间 签离时间 。其中时间按“小时:分钟:秒钟”(各占2位)给出,证件号码是长度不超过15的字符串。
输出描述
对每一天的记录输出1行,即当天开门和关门人的证件号码,中间用1空格分隔。
注意:在裁判的标准测试输入中,所有记录保证完整,每个人的签到时间在签离时间之前,且没有多人同时签到或者签离的情况。
输入
3
CS301111 15:30:28 17:00:10
SC3021234 08:00:00 11:25:25
CS301133 21:45:00 21:58:40
输出
SC3021234 CS301133
注意点
1. 巧用字符串比较。
2. 此题实际上没有必要用排序。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct Record{
string id;
char in[30];
char out[30];
};
bool cmp1(Record a,Record b)
{
return strcmp(a.in,b.in)<0;//按照到的时间从小到大
}
bool cmp2(Record a,Record b)
{
return strcmp(a.out,b.out)<0;//按照离开的时间从小到大
}
Record record[1001];
int main(void)
{
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>record[i].id>>record[i].in>>record[i].out;
}
sort(record,record+n,cmp1);
cout<<record[0].id<<" ";
sort(record,record+n,cmp2);
cout<<record[n-1].id<<endl;
return 0;
}