桶排序

问题来源:

啊哈 算法-p2
期末考试完了老师要将同 学们的分数按照从高到低排序。小哼的班上只有 5个同学,这 5个同学分别考了 5分、3分、 5分、2分和 8分,哎考得真是惨不忍睹(满分是 10分)。接下来将分数进行从大到小排序, 排序后是 8 5 5 3 2。你有没有什么好方法编写一段程序,让计算机随机读入 5个数然后将这 5个数从大到小输出?

问题分析:

在这里插入图片描述
其实,a[0]~a[10]中的数值其实就是 0分到 10分每个分数出现的次数。接下来, 我们只需要将出现过的分数打印出来就可以了,出现几次就打印几次,具体如下。
a[0]为 0,表示“0”没有出现过,不打印。
a[1]为 0,表示“1”没有出现过,不打印。
a[2]为 1,表示“2”出现过 1次,打印 2。
a[3]为 1,表示“3”出现过 1次,打印 3。
a[4]为 0,表示“4”没有出现过,不打印。
a[5]为 2,表示“5”出现过 2次,打印 5 5。
a[6]为 0,表示“6”没有出现过,不打印。
a[7]为 0,表示“7”没有出现过,不打印。
a[8]为 1,表示“8”出现过 1次,打印 8。
a[9]为 0,表示“9”没有出现过,不打印。
a[10]为 0,表示“10”没有出现过,不打印。

核心代码:

#include<iostream>
using namespace std;
int main()
{
	int i,j,k,book[10];
	for(i=0;i<10;i++)
		book[i]=0;
	for(j=0;j<5;j++)
	{
		scanf("%d",&i);
		book[i]++;
	}
	for(i=0;i<10;i++)
	{
		for(k=0;k<book[i];k++)
		printf("%d ",i);
	}
	return 0;
 } 

降序:

#include<iostream>
using namespace std;
int main()
{
	int i,j,k,a[10];
	for(i=0;i<10;i++)
		a[i]=0;
	for(j=0;j<5;j++)
	{
		scanf("%d",&i);
		a[i]++;
	}
	for(i=9;i>=0;i--)
	{
		for(k=0;k<a[i];k++)
		printf("%d ",i);
	}
	return 0;
 }  

总结:

1.由题干确定数组的范围→初始化数组为0→输入要排序的数字→输出。
2.使用桶排序要已知要排序的范围和数量。
3.这并不是真正的桶排序算法,这只是简化版的桶排序,真正的桶排序算法要比这个更加复杂。
4.桶排序的时间复杂度:代码中第 6行的循环一共循环了 m次(m为桶的个数),第 8行的代码循环了 n次(n为待排序数的个数),第 13行和第 15行一共循环了 m+n次。 所以整个排序算法一共执行了 m+n+m+n次。用大写字母 O来表示时间复杂度,因此该算法的时间复杂度是 O(m+n+m+n)即 O(2*(m+n))。因为时间复杂度可以忽略较小的常数,最终桶排序的时间复杂度为 O(m+n)。还有一点,在表示时间复杂度的时候,n和m通常用大写字母即 O(M+N)。
5.桶排序的缺点:非常浪费空间!例如需要排序数的范围是 0-2100000000之间,则需要申请 2100000001个变量,也就是说要写成 int book[2100000001]。因为需要用 2100000001个“桶”来存储0~2100000000之间每一个数出现的次数。即便只给5个数进行排序(例如这 5个数是 1、1912345678、2100000000、18000000和 912345678),也仍然需要 2100000001个“桶”,这真是太浪费空间了!而且,也不能解决小数排序问题,比如将 5.56789、2.12、1.1、3.123、4.1234 这五个数进行从小到大排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值