又快又简单的排序——桶排序(简单入门篇)

桶排序种种

排序在日常使用中非常多,这里来介绍一个简单快速的排序算法,主要用于简单少量普通的快速排序。这里先介绍较为容易理解的简单的 桶排序算法
本文以 C语言为例,编译使用VS2015. φ(゜▽゜*)♪

简单介绍

假设我们有一个普通数组为{5,3,5,2,8},下面我们要对他进行排序,这里使用分数来做个例子,就可以假设有五个小人,他们考试分别取得了如上数组的成绩(满分10分),然后我们来做个记录,用一个大小为11的数组,即a[0]-a[10] 来表示他们所有可能的得分,开始时将数组a初始化为0,表示这些分数都没有人得过,然后我们依次读入他们的分数,
第一个人是5分,我们就把对应的a[5] 的值加1,表示5分出现了一次,
第二个人是3分,我们就把对应的a[3] 的值加1,表示3分出现了一次,
第三个人是5分,我们就把对应的a[5] 的值加1,这时,我们的a[5] 的值就是2 了,
然后下面依次读入并加1,就可以得到如下的一张直观图:
桶排序图
仔细看这个图,再对照我们要排序的数组{5,3,5,2,8},我们把上面数组值为零的舍弃不打印,其他大于0的 是几就打印几次,比如,a[0] a[1] 都不打印,a[2] a[3] 分别打印一次,分别打印2 和3,后面的a[5] 打印5 两次,a[8] 打印8一次。
这样就在屏幕上输出了 2 3 5 5 8 就是我们的排序结果了

具体实现

下面是具体的实现代码,相关的注释我都有写在代码中,算是较为详细的了

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#define size 1001
//通过对size的约束,就可以实现对于0-size-1 的数字的排序

void Init(int a[])  //对桶的初始化
{
	int i;
	for (i = 0; i <= size - 1; i++) //注意等于号,要注意初始化的个数
	{
		a[i] = 0;  //把每个桶都初始化为空
	}
}

void Bucket_sort(int b[])  //桶排序算法实现
{
	int i,j;
	for ( i = size-1; i >=0 ; i--)  //记录桶的个数
	//这里是由大到小的输出,当然也可以改为有小到大输出,for(i=0;i<size-1;i++)就可以了
	{
		for (j = 1; j <= b[i]; j++)
		{
			printf("%d	", i);  //将有记录的桶的编号输出

		}
	}
	printf("\n");
}

int main()
{

	int book[size];  
	//这里将排序数组命名为book是取记录,标记的意思,具体的关于变量命名也是要时刻注意的
	int i, t;
	int n=0;
	Init(book);  //初始化函数

	printf("请输入要排序的数据个数:");
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
	{
		printf("请输入第%d个数据: ", i);
		scanf("%d", &t);  //循环读入数据
		book[t]++;  //将数据放入待排序的数组中
	}

	printf("排序结果为:\n");
	Bucket_sort(book);  //桶排序函数



	return 0;
}

下面是运行结果:
运行结果

看完代码其实可以发现,桶排序就是用一个桶来作为标记,记录每个数字出现的次数,就像是我们通过读入数据,然后在每个桶中来放置小旗子一样,通过小旗子的数量来进行输出,这样一想,其实很快就会发现这个排序算法有着很大的改进空间。

分析与改进

下面我们来分析一下这个排序算法,其实这个排序主要就是两个嵌套的循环,而且还并不是像冒泡排序那样的嵌套循环,因为第二个的循环条件是j <= b[i],所以我们可以认为时间复杂度是O(m+n),这个时间复杂度要比不少排序算法优秀了,至少在速度方面真的很不错(关于冒泡排序的具体复杂度和优化可以看这里 冒泡排序实现及优化),但是如果分析空间复杂度的话就会发现,如果要排序大小相距很大的数据,比如仅仅是排序5 2 65536,我们就需要用到65537个桶,这些空间占用是很恐怖的,而且如果仅仅是和冒泡排序相比的话也可以发现,桶排序是单纯的依赖数组进行的,也就是说它仅仅可以做到对数据排序,而不能把数据的其他信息也一并排序,就比如排序学生成绩,总不能就排序成绩,而不对应他们的学号姓名吧`(>﹏<)′。
当然了对于这些问题,真正的桶排序是有一定的解决办法的,这里先介绍这个简单版的桶排序,等到后续再介绍完整版的 高效的的桶排序!(。・∀・)ノ゙

最后

感谢观赏,一起提高,慢慢变强。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值