桶排序种种
排序在日常使用中非常多,这里来介绍一个简单快速的排序算法,主要用于简单少量普通的快速排序。这里先介绍较为容易理解的简单的 桶排序算法
本文以 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个桶,这些空间占用是很恐怖的,而且如果仅仅是和冒泡排序相比的话也可以发现,桶排序是单纯的依赖数组进行的,也就是说它仅仅可以做到对数据排序,而不能把数据的其他信息也一并排序,就比如排序学生成绩,总不能就排序成绩,而不对应他们的学号姓名吧`(>﹏<)′。
当然了对于这些问题,真正的桶排序是有一定的解决办法的,这里先介绍这个简单版的桶排序,等到后续再介绍完整版的 高效的的桶排序!(。・∀・)ノ゙
最后
感谢观赏,一起提高,慢慢变强。