最简单的排序算法--桶排序

什么是桶排序呢?在讲这个之前,我们先提提什么是排序和算法。

一般来说,排序是指将对一组大小关系混乱的数据,用从大到小或者从小到大的顺序进行排列,使其拥有大小关系确定的排列顺序。就比如一个班的学生,根据身高,从高到低排队或者从低到高排队,这个过程就叫排序。

   可能你们会觉得谁会不懂排序是什么呢,虽然排序的概念结合我们的实际生活来说很容易理解,但是如果是数学统计上的一大组数据,排起序来可不像比身高一样简单,面对不同数据,需要用到不同的排序方式来进行高效快速的排序,如果你仔细想想我们比身高的时候是不是有很多方法。

比如,可以先找你们班里的一个,让他跟一个人比身高,比他高站他左边,比他矮站他的右边。所有人比完以后,左右俩边各找一个人,又继续重复比较,直到,所有人的位置按身高从高到低或者从低到高排了起来。其实这个就是以后要说的 快速排序。你也可以把人分成一堆 一堆的来排序,也可以每次选一个人左右比较身高,再来交换。这些不同的方法,有不同的时间效率和空间效率,可以说做是不同的算法。

今天,来说的桶排序算法(严格意义上真实的桶排序比这个复杂一点,但这个更适合作为初学者的我们)是一种速度很快的一种排序,所以让我们简单的了解一下什么是桶排序。

假设我们刚考完了数学期末考试,一个班里有10个同学,每个同学考的分数都不一样且是0<=grade<=100内的整数,

如果成绩是 :{ 21 ,34 ,56 ,43 ,17 ,64 ,59, 81 ,79 ,93}。我们要如何对该成绩进行排序呢?

我们把 0-100分中内每个分数想象成一个桶,比如 100分是一个桶,99分是另外一个桶以此类推。我们对成绩进行遍历,就像从一堆有成绩数字的号码球里选一个,我们在选球之前,必须要先有桶吧,所以我们因为知道学生成绩是从0-100的,所以我们搬来了 编号从0-100的桶(按顺序摆放成水平一行),一种101个,且每个桶都要空,此时假设选出21号球(即代表考试考了21分的学生的成绩),因为我们选出的桶里有编号为21的桶,所以将小球放入21号箱子内,此时21一号箱子内有了一个小球而其他桶没有小球,我们以此类推剩余学生的成绩,最后编号为:21,34,56,43,17,64,59,81,79,93的箱子里分别有一个小球,我们最后检查每个箱子的情况,如果箱子里有小球,将桶往前推一步(注意:我们之前的条件是101个编号是0-100的桶,按照编号大小顺序排列成一行),最后将退出来的桶子,在并到一起。我们就得到了桶子序号分别是 17,21,34,43,56,59,64,79,81,83的桶子顺序,而桶子里的小球(即学生成绩)完成了从小到大排序。我相信你能想象这个排序的过程。下面我将运用C语言的代码,一步步将上面的过程用代码语言依次实现。

首先我们要知道排序的数据总数,我们设一个变量来获取存储它

	//这个变量就是 要排序的数据总数,对上面来说就是要比较成绩的学生人数
	int n=0;
	//输入 学生人数 比如 10
	scanf("%d",&n);

然后为因为成绩是0-100,且有101个桶,所以我们定义一个数组即来当桶

	// 因为成绩是0-100,我们要有 101个桶,且编号是0-101,所以我们定义一个数组
	int bucket[101];

为了确保桶里是空的,我们要对桶进行检查,即可认为对数组每个元素

	int i = 0;
	for (i = 0; i < 100; i++){
		bucket[i] = 0;
	}

进行初始化为0

然后,我们要开始输入成绩了,因为我们已经知道有n个数据了,所以我们要输入n次

如果,成绩号即小球的号码,等于桶号,把球放入桶内,即以该桶号为下标的数组元素的值加一

	int grade = 0;//学生的成绩
	//现在我们输入 n 次 学生的成绩,相当于从桶里拿球
	for (i = 0; i < n; i++){
		scanf("%d",&grade);
		bucket[grade]++;//以该成绩为编号的 桶子 ,值加一,相当于放了该小球进去
	}

最后,我们要判断桶里是不是有球,如果有球,即桶里球的数量不为0,把桶推出来(即桶号输出来)

	//现在是最后的判断输出,相当于看桶里有没有球,有球的往前推,输出相当于将推出的桶合并排序
	for (i = 0; i < 100; i++){
		if (bucket[i]>0){//如果桶里有球,则输出编号
			printf("%d ",i);
		}
	}

整个代码是:

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
int main(){
	//这个变量就是 要排序的数据总数,对上面来说就是要比较成绩的学生人数
	int n=0;
	//输入 学生人数 比如 10
	scanf("%d",&n);
	// 因为成绩是0-100,我们要有 101个桶,且编号是0-101,所以我们定义一个数组
	int bucket[101];
	//因为我们要确保每个桶里没有小球,所以我们要对数组进行初始化
	int i = 0;
	for (i = 0; i < 100; i++){
		bucket[i] = 0;
	}
	int grade = 0;//学生的成绩
	//现在我们输入 n 次 学生的成绩,相当于从桶里拿球
	for (i = 0; i < n; i++){
		scanf("%d",&grade);
		bucket[grade]++;//以该成绩为编号的 桶子 ,值加一,相当于放了该小球进去
	}
	//现在是最后的判断输出,相当于看桶里有没有球,有球的往前推,输出相当于将推出的桶合并排序
	for (i = 0; i < 100; i++){
		if (bucket[i]>0){//如果桶里有球,则输出编号
			printf("%d ",i);
		}
	}

	return 0;
}

输入输出测试结果:

 这样我们就成功实现了桶排序,终于知道为什么叫桶排序了吧,简单来说,桶排序就是往带有顺序和编号的桶里投有相同编号的小球,如果桶里有球,就把桶号输出来,因为桶号本身是有顺序的,我们往桶里扔进去的小球也因此有了顺序。但是我们也发现了一个问题,这个排序很容易浪费桶,就拿上面的栗子,我们拿出来101桶最后却只用了10个,造成了浪费,且我们的编号都是大于等于0的整数,对负数,小数,我们无法用这种方法来排序,但是这个方法是非常快的,因为计算机可以在一秒内进行上亿次计算,所以即使是上亿个符合条件的数字,都可以用桶排序来快速实现。

我后续还会发布关于几种常见排序的文章,欢迎大家关注我,我们一起学习进步,如果有错误或者问题,请评论指出不足,我也会积极回复问题,谢谢大家!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值