排序
目录
7.P2676 [USACO07DEC]Bookshelf B
一、实例:
1.P1271 【深基9.例1】选举学生会
P1271 【深基9.例1】选举学生会 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题就是将m张选票从小到大进行排序,由于数量比较大,为了不超时我们使用快排。
#include<stdio.h>
int a[10000000];
int quick_sort(int *a,int low,int high)
{
int i=low,j=high;
int mid=(i+j)/2;
int temp1;
if(a[j]<a[i])
{
temp1=a[j];
a[j]=a[i];
a[i]=temp1;
}
if(a[j]<a[mid])
{
temp1=a[j];
a[j]=a[mid];
a[mid]=temp1;
}
if(a[mid]>a[i])
{
temp1=a[i];
a[i]=a[mid];
a[mid]=temp1;
}
int temp=a[i];
while(i<j)
{
while(i<j&&a[j]>=temp)
{
j--;
}
a[i]=a[j];
while(i<j&&a[i]<=temp)
{
i++;
}
a[j]=a[i];
}
a[i]=temp;
if(i-1>low)
quick_sort(a,low,i-1);
if(i+1<high)
quick_sort(a,i+1,high);
return 0;
}
int main(void)
{
int n,i,m;
scanf("%d%d",&m,&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
quick_sort(a,0,n-1);
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
2.P1177 【模板】快速排序
P1177 【模板】快速排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<stdio.h>
int a[10000000];
int quick_sort(int low,int high)
{
int i=low,j=high;
int mid=(i+j)/2;
int temp1;
if(a[j]<a[i])
{
temp1=a[j];
a[j]=a[i];
a[i]=temp1;
}
if(a[j]<a[mid])
{
temp1=a[j];
a[j]=a[mid];
a[mid]=temp1;
}
if(a[mid]>a[i])
{
temp1=a[i];
a[i]=a[mid];
a[mid]=temp1;
}
int temp=a[i];
while(i<j)
{
while(i<j&&a[j]>=temp)
{
j--;
}
a[i]=a[j];
while(i<j&&a[i]<=temp)
{
i++;
}
a[j]=a[i];
}
a[i]=temp;
if(i-1>low)
quick_sort(low,i-1);
if(i+1<high)
quick_sort(i+1,high);
return 0;
}
int main(void)
{
int n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
quick_sort(0,n-1);
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
3.P1923 【深基9.例4】求第 k 小的数
P1923 【深基9.例4】求第 k 小的数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题就是将n个数字排好序,输出第k小的数。
#include<stdio.h>
int a[10000000];
int quick_sort(int *a,int low,int high)
{
int i=low,j=high;
int mid=(i+j)/2;
int temp1;
if(a[j]<a[i])
{
temp1=a[j];
a[j]=a[i];
a[i]=temp1;
}
if(a[j]<a[mid])
{
temp1=a[j];
a[j]=a[mid];
a[mid]=temp1;
}
if(a[mid]>a[i])
{
temp1=a[i];
a[i]=a[mid];
a[mid]=temp1;
}
int temp=a[i];
while(i<j)
{
while(i<j&&a[j]>=temp)
{
j--;
}
a[i]=a[j];
while(i<j&&a[i]<=temp)
{
i++;
}
a[j]=a[i];
}
a[i]=temp;
if(i-1>low)
quick_sort(a,low,i-1);
if(i+1<high)
quick_sort(a,i+1,high);
return 0;
}
int main(void)
{
int n,i,k;
scanf("%d%d",&n,&k);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
quick_sort(a,0,n-1);
printf("%d",a[k]);
return 0;
}
4.P1059 [NOIP2006 普及组] 明明的随机数
P1059 [NOIP2006 普及组] 明明的随机数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
先将数组中的重复数字进行删除,每删除一个就将后面的覆盖前面的,然后再进行排序。
#include <stdio.h>
int main(void)
{
int n,a[100],i,j,k,temp;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
//删除重复数字
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(a[i]==a[j])
{
for(k=j;k<n;k++)
{
a[k]=a[k+1];
}
n--;
j--;//因为有j++,如果不减一下,等会比的话就从下一位开始比了
}
}
}
for(i=0;i<n;i++)
{
for(j=0;j<n-1-i;j++)
{
if(a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
printf("%d\n",n);
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
5.P1093 [NOIP2007 普及组] 奖学金
P1093 [NOIP2007 普及组] 奖学金 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
结构体排序,先将学号和总成绩储存在结构体数组中,然后先按照总成绩排序,如果总成绩相同的,比较语文成绩,如果语文成绩也相同,最后比较学号,学号小的排在前面。
#include<stdio.h>
struct student
{
int C;
int M;
int E;
int sum;
int num;
}stu[300];
int main(void)
{
struct student temp;
int n,i,j;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d%d%d",&stu[i].C,&stu[i].M,&stu[i].E);
//学号
for(i=0;i<n;i++)
stu[i].num=i+1;
for(i=0;i<n;i++)
stu[i].sum=stu[i].C+stu[i].M+stu[i].E;
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(stu[i].sum<stu[j].sum)
{
temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
if(stu[i].sum==stu[j].sum)
{
if(stu[i].C<stu[j].C)
{
temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
}
if(stu[i].sum==stu[j].sum)
{
if(stu[i].C==stu[j].C)
{
if(stu[i].num>stu[j].num)
{
temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
}
}
}
}
for(i=0;i<5;i++)
printf("%d %d\n",stu[i].num,stu[i].sum);
return 0;
}
6.P1781 宇宙总统
P1781 宇宙总统 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
将输入的数字储存在数组中,计算出每个字符串的长度,将最长的放在最前面,然后在比较最长的有没有相同长度的,然后比较大小,将最大的放在最前面,最后与之前复制的数组比较,输出号数,然后输出票数。
#include<stdio.h>
#include<string.h>
struct candidate
{
char a[100];
int l;//储存各个字符串的长度
}cand[20];
int main(void)
{
struct candidate temp;
int n,i,j,t;
char b[20][100];
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%s",cand[i].a);
for(i=0;i<n;i++)
strcpy(b[i],cand[i].a);
//计算各个字符串长度
for(i=0;i<n;i++)
cand[i].l=strlen(cand[i].a);
//排序字符串长度
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(cand[i].l<cand[j].l)
{
temp=cand[i];
cand[i]=cand[j];
cand[j]=temp;
}
}
}
//比较有没有长度相同的
t=0;
for(i=1;i<n;i++)
{
if(cand[t].l==cand[i].l)
{
if(strcmp(cand[t].a,cand[i].a)<0)
{
temp=cand[t];
cand[t]=cand[i];
cand[i]=temp;
}
}
else
break;
}
//输出号数
for(i=0;i<n;i++)
{
if(strcmp(b[i],cand[0].a)==0)
{
printf("%d\n",i+1);
break;
}
}
//输出票数
printf("%s",cand[0].a);
return 0;
}
7.P2676 [USACO07DEC]Bookshelf B
P2676 [USACO07DEC]Bookshelf B - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
将牛按照身高从大到小进行排序,依次累加,直到高度大于等于书架顶部,输出最少奶牛的数量。
#include<stdio.h>
#include<math.h>
int main(void)
{
int n,b,t,s=0,k=0;//s记录牛的身高,k记录牛的数量
int a[20000];
int i,j;
scanf("%d%d",&n,&b);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
//插入排序
for(i=1;i<n;i++)
{
t=a[i];
for(j=i-1;j>=0&&a[j]>t;j--)//如果前面的大于后面的
{
a[j+1]=a[j];//前面的赋值给后面的
}
a[j+1]=t;//因为j--,所以是j+1,将原来后面的赋值给前面的
}
for(i=n-1;i>=0;i--)
{
s+=a[i];
k++;
if(s>=b)
{
printf("%d",k);
return 0;
}
}
return 0;
}
8.P1116 车厢重组
P1116 车厢重组 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题就是将车厢按车厢号从小到大排列,最少用多少步就能将车厢排序,每进行一次交换,就将k++,z最后输出k。
#include<stdio.h>
int main(void)
{
int n,a[10000],k=0;
int i,j,t;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n-1;i++)
{
for(j=0;j<n-i-1;j++)
{
if(a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
k++;
}
}
}
printf("%d",k);
return 0;
}
9.P1152 欢乐的跳
P1152 欢乐的跳 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
将n个元素的整数数组两个连续元素之间差的绝对值储存到另一个数组中,从小到大进行排序,如果包括了1到n-1之间的所有整数,则输出Jolly,否则输出Not jolly。
#include<stdio.h>
#include<math.h>
int main(void)
{
int a[1000],b[1000];
int n,i,j,t;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
{
b[i]=fabs(a[i]-a[i+1]);
}
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n-1;j++)
{
if(b[i]>b[j])
{
t=b[i];
b[i]=b[j];
b[j]=t;
}
}
}
for(i=0;i<n-1;i++)
{
if(b[i]!=i+1)
{
printf("Not jolly");
return 0;
}
}
printf("Jolly");
return 0;
}
10.P1068 [NOIP2009 普及组] 分数线划定
P1068 [NOIP2009 普及组] 分数线划定 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
面试分数线为排名第p=m \ 150%(向下取整)名的选手的分数,按笔试成绩排名从大到小进行排序,如果第p名成绩与后面的相同,则将p++,最后如果成绩相同,则按照报名号进行排序。
#include<stdio.h>
#include<math.h>
struct people
{
int num;
int sorce;
}stu[5000];
int main(void)
{
struct people temp;
int n,p,i,j,m;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
scanf("%d%d",&stu[i].num,&stu[i].sorce);
p=floor(m*1.5);
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(stu[i].sorce<stu[j].sorce)
{
temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
}
}
for(i=p-1;i<n;i++)
{
if(stu[i].sorce==stu[i+1].sorce)
{
p++;
}
else
break;
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(stu[i].sorce==stu[j].sorce)
{
if(stu[i].num>stu[j].num)
{
temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
}
}
}
printf("%d %d\n",stu[p-1].sorce,p);
for(i=0;i<p;i++)
printf("%d %d\n",stu[i].num,stu[i].sorce);
return 0;
}
11.P5143 攀爬者
P5143 攀爬者 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<stdio.h>
#include<math.h>
struct coord//坐标
{
int x;
int y;
int z;
}point[50000];
int quick_sort(int low,int high)
{
int t;
int i=low,j=high;
int temp=point[i].z;
while(i<j)
{
while(i<j&&point[j].z>=temp)
{
j--;
}
point[i].z=point[j].z;
t=point[i].x;
point[i].x=point[j].x;
point[j].x=t;
t=point[i].y;
point[i].y=point[j].y;
point[j].y=t;
while(i<j&&point[i].z<=temp)
{
i++;
}
point[j].z=point[i].z;
t=point[i].x;
point[i].x=point[j].x;
point[j].x=t;
t=point[i].y;
point[i].y=point[j].y;
point[j].y=t;
}
point[i].z=temp;
if(i-1>low)
quick_sort(low,i-1);
if(i+1<high)
quick_sort(i+1,high);
return 0;
}
int main(void)
{
int n,i,j;
double s=0,a,b,c,d;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d%d%d",&point[i].x,&point[i].y,&point[i].z);
quick_sort(0,n-1);
for(i=0;i<n-1;i++)//n的话会多循环一次
{
a=pow((point[i].x-point[i+1].x),2);
b=pow((point[i].y-point[i+1].y),2);
c=pow((point[i].z-point[i+1].z),2);
d=a+b+c;
s=s+sqrt(d);
}
printf("%.3lf",s);
return 0;
}
12.P1104 生日
P1104 生日 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<stdio.h>
#include<string.h>
struct student
{
char name[20];
int year;
int month;
int day;
int in;//输入顺序
}stu[100];
int main(void)
{
struct student temp;
int i,j,n;
int t;//
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%s%d%d%d",stu[i].name,&stu[i].year,&stu[i].month,&stu[i].day);
for(i=0;i<n;i++)
stu[i].in=i;
//比较年
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(stu[i].year>stu[j].year)
{
temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
}
}
//比较月
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(stu[i].year==stu[j].year)
{
if(stu[i].month>stu[j].month)
{
temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
}
}
}
//比较日
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(stu[i].year==stu[j].year)
{
if(stu[i].month==stu[j].month)
{
if(stu[i].day>stu[j].day)
{
temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
}
}
}
}
for(i=0;i<n;i++)
printf("%s\n",stu[i].name);
return 0;
}
13.P1012 [NOIP1998 提高组] 拼数
P1012 [NOIP1998 提高组] 拼数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题直接用字典序排序最后一个会WA,如果输入是321 32,按照字典序排序是32132,但是这样没有32321大,所以需要将a[i]+a[j]和a[j]+a[i]进行比较。
#include<stdio.h>
#include<string.h>
int main(void)
{
int n,i,j;
char a[20][100],t1[100],t2[100];
char temp[100];
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%s",a[i]);
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
strcpy(t1,a[i]);
strcpy(t2,a[j]);
strcat(t1,a[j]);
strcat(t2,a[i]);
if(strcmp(t1,t2)<0)
{
strcpy(temp,a[i]);
strcpy(a[i],a[j]);
strcpy(a[j],temp);
}
memset(t1,0,sizeof(t1));//将数组t1和t2的空间初始化为0
memset(t2,0,sizeof(t2));
}
}
for(i=0;i<n;i++)
printf("%s",a[i]);
return 0;
}
二、总结
1.经过这一周的练习排序,可以感觉到自己又有了一些提升,但是面对提高组及以上的题还是有些吃力,但是有了一些进步。
2.这一周就是掌握了几种排序的模板,可以在不同的问题下,应用最适合的排序方法。
3.有的题使用普通快排也会出现超时,所以我们需要对快排做出一些优化,比如选择基准的时候进行三点取中的方法。