您的位置:首页 > 其它

【算法学习笔记】03.白书练习题stat(排序入门:冒泡,桶)

2014-07-19 19:48 357 查看
原题:

输入一些学生的分数,哪个分数出现的次数最多?如果有多个并列,从小到大输出。

任务1,分数为不超过100的非负整数。(题眼。)

任务2,分数为不超过100.00的非负实数。保留两位小数(两位的处理)

依照惯例,先看看我的垃圾代码。

#include <stdio.h>
#include <string.h>
#include <math.h>
int b[100];
double a[100],c[100];
int main()
{
int i =0,flag,j,al,max=0,k=0,cl;
double t;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
while(scanf("%lf",&t)==1)
{
flag=0;
for(j=0;j<i;j++)
{
if(fabs(a[j]-t)<=0.000000001)
{
b[j]++;
flag =1;
if(b[j]>max)
{
max=b[j];
memset(c,0,sizeof(c));
k=0;
c[k++]=a[j];
}
else if(b[j]==max)
{
c[k++]=a[j];
}
break;
}
}
if(!flag)
{
a[i]=t;
b[i]=1;
i++;
}
}
al=i;//利用i来记录a的长度 不同数字的个数
cl=k;//c的长度 最多出现的数字的个数

//给c选择排序
for(i=0;i<cl;i++)
{
for(j=i;j<cl;j++)
{
if(c[i]>c[j])
{
t=c[j];
c[j]=c[i];
c[i]=t;
}
}
}

printf("%d\n",al);
for(i=0;i<al;i++)
printf("%.2lf ",a[i]);
printf("\n");
for(i=0;i<al;i++)
printf("%d ",b[i]);
printf("\n");
for(i=0;i<cl;i++)
printf("%.2lf ",c[i]);
printf("\n");

}


此处为任务2的代码,任务1直接将a,c换成int型数组即可。

此方法很弱智地绕弯型思维,竟然用了三个数组完成这件事,而且数组长度明显存在隐患。因为方法错误而产生了各种较为难以解决的问题。

此方法的思维模式是:

1.如何将输入的数字存起来,并且记录其出现的次数。

2.如何找到出现最多次的数字,并存起来。(此处需要动态重置数组)

3.如何排序

于是为了解决这三个问题,花费了非常复杂的代码。虽然见佛当佛见鬼杀鬼,但是在性能上明显输了。而且有缺点。

1.数组长度漏洞

2.doule型比较存在隐患

此时,再看看什么叫算法艺术。

int max=0,n=0,a[100]={0},x;
while(cin >> x)
{
if(++a[x]>max) max=a[x];
if(x>n) n=x;//此处记录最大的分数,用来缩小循环次数
}
for(int i=0;i<=n;i++) 
if(a[i]==max) cout << i << " ";


多么简洁,多么完美,多么像一个清新可人的少女阿我去。。。

启发

1.数组下标本身就是一个有序数组,因为0~100,正好是题目中要求的范围,

此举(1) 解决了一个记录输入数据的数组,节省空间。(2)解决了排序的问题,直接按序输出,即可。

2.此代码简洁异常。比如++的利用,比如a[100]={0}的利用,不过这个貌似是才c++的特殊用法。c里是memset()

3.这才是直接型的思维。 你本来要输入未知个数个数据,但是这个数据的范围是有限的,而且你还要在这些数据上做文章。

那么用数组下标来表示数据,用数组内容来表示个数,极其合适。顺便解决了排序的问题

4.扩展性好,比如看任务2的代码。

int max=0,n=-1,a[10010]={0}; //is hash?
double x;
while(cin >> x){
if(++a[(int)floor(x*100)]>max) max=a[(int)floor(x*100+0.5)];// +0.5防止浮点数陷阱
if((int)floor(x*100)>n) n=(int)floor(x*100);//用来缩小循环次数
}
for(int i=0;i<=n;i++) if(a[i]==max)
printf("%.2lf ",(double)i/100);
//cout << setiosflags(ios::fixed) << setprecision(2) << (double)i/100 << " ";


接4. 因为要解决有关二位小数的问题,但是数组下标只能是整数。所以不妨用10000来表示100.00 用2233来表示22.33

简直完美。

今天才知道这个叫做桶排序

今天拿冒泡排序的代码去试wikioi的排序题。。。超时太严重了

在题解中了解到了,归并排序,,快速排序,希尔排序,等等还有c++的stl中的sort,貌似也不超时。

选择排序,是一种不稳定的排序,冒泡排序是一种稳定排序。。。我之前一直弄混了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: