首先我要吐槽一下搜索引擎坑我的故事
排序算法有很多,但第一次听到桶排序
这个算法时,瞬间就被它可爱的名字给Q到,正好我看的一本C++书上有道桶排序的题目,费了一番功夫后解决了这道题,于是,就去百度,想看看大神们的桶排序
算法是怎样写的,结果……搜索引擎把我坑惨了,如下图:
搜索到的前n条介绍,都很令人失望,我把他们的代码亲自跑了一遍,都是只能对10以内的数据排序???心里一万个mmp,如果真是这样,那还要桶排序
干嘛?
我并不清楚正宗的桶排序
到底是什么样子的,但我按照书上的题目,实现了一个功能还算强大的桶排序
,由于我将数据储存为string类型
,所以可以对很大的数排序,至于这个数到底有多大,那要看string类型
数据的长度了(我又手贱百度了一下,好像这个数大到形容不出来……)。
书上的原题是这样的(我感觉这道题已经把桶排序
介绍的很到位了,比百度上的各种解释都要清楚):
桶排序(bucket sort)
从一个一维的待排序的正整数数组和一个二维整数数组开始,其中,二维数组的行下标是从0到9,列下标时从0到n-1,n时一位数组中待排序值的个数。这个二维数组的每一行都称为一个桶。编写一个函数bucketSort,它采用一个整数数组和该数组的大小作为参数,并执行以下操作:
a) 对于一位数组的每一个值,根据值的个位数,将其放到桶数组的各行中。例如,97放在第7行,3放在第3行,100放在第0行。这称为“分布过程”。
b) 在桶数组中逐行循环遍历 ,并把值复制回原始数组。这称为“收集过程”。上述值在一位数组中的新次序是100,3,97。
c) 对随后的每个数位(十位,百位,千位等)重复这一过程。
在第二遍排序时,100放在第0行,3放在第0行(因为3没有个位),97放在第9行。收集过程之后,一维数组中值的顺序为100,3,97。在第三遍排序时,100放在第1行,3放在第0行,97放在第0行(在3之后)。在最后一次收集过程之后,原始数组就是有序的了。
不扯废话了,直接上代码:
#include <iostream>
#include <string>
using namespace std;
//将字符串中指定下标处的字符转换为对应的数字
int stringToInt( string str, int sub )
{
return ((int)str[sub] - 48);
}
//桶排序,参数len:待排序数据的个数
void bucketSort( string str[], int len )
{
string arr2[10][len]; //桶
int i;
int j;
//初始化桶
for ( i = 0; i < 10; i++) {
for ( j = 0; j < len; j++) {
arr2[i][j] = "e"; //令桶中所有元素的值都为字符:e,避免与数字冲突(可以换成其它字符)
}
}
int subStr; //字符串中,指定下标处的字符所对应的数字
int iSub; //下标
int flag = 1; //记录循环次数
int maxLength = 0; //待排序的一组数中,最长的数的长度
//找出桶中最大数的长度(用于判断循环是否需要结束)
for ( i = 0; i < len; i++) {
if (str[i].length() > maxLength) {
maxLength = str[i].length();
}
}
//排序
while(1) {
for ( i = 0; i < len; i++) {
iSub = str[i].length() - flag; //下标(初始取最后一个下标)
if (iSub < 0) { //下标为负的时候,令下标处的字符对应的数字为0
subStr = 0;
} else {
subStr = stringToInt(str[i], iSub); //将iSub下标处的字符,转换为对应的数字
}
//将数字存入对应的桶中
for ( j = 0; j < len; j++) {
if (arr2[subStr][j] == "e") {
arr2[subStr][j] = str[i];
break;
}
}
}
int counter = 0; //计数器
//收集桶中的数字
for ( i = 0; i < 10; i++) {
for ( j = 0; j < len; j++) {
if (arr2[i][j] != "e") {
str[counter] = arr2[i][j];
counter += 1;
}
}
}
flag += 1;
//循环maxLength次后,排序结束,此时flag值为maxLength + 1
if (flag == (maxLength + 1)) {
//打印结果
for ( i = 0; i < len; i++) {
cout << str[i] << " ";
}
cout << endl;
return;
}
//重置桶
for ( i = 0; i < 10; i++) {
for ( j = 0; j < len; j++) {
arr2[i][j] = "e";
}
}
}
}
int main()
{
string arr1[15] = { "33", "28", "0", "1", "436", "6", "100", "9", "211", "223", "95", "20", "560", "16", "999" };
string arr2[10] = { "1", "28", "33", "100", "9", "223", "95", "560", "16", "999" };
string arr3[5] = { "436", "6", "20", "99", "211" };
string arr4[5] = { "10000", "6000000", "0", "999999", "11111111" };
bucketSort(arr1, 15); //1 6 9 16 20 28 33 95 99 100 211 223 436 560 999
bucketSort(arr2, 10); //1 9 16 28 33 95 100 223 560 999
bucketSort(arr3, 5); //6 20 99 211 436
bucketSort(arr4, 5); //0 10000 999999 6000000 11111111
return 0;
}
编译器:CodeBlocks
对代码的补充说明:
首先,我将数据储存为string类型
一是因为能对很大很大的数排序,二是取某个数的某个位上的数比较方便。
其次,从第四组测试数据
可以看出,对很大很大的数
排序完全没问题。
但是有个缺点,就是不能对负数排序,emmm……可以把代码改进一下。
代码思路简单,注释也比较详细,看我这篇博客的大佬们肯定都能看懂滴,就不再赘述了。
结语:因水平有限,文章有错误或者不足,欢迎评论,希望轻拍,一起进步哦!
END!