引子
上一期,我们用了冒泡排序完成了一道十分神奇的"幼儿园题",而在上期最后我们留了一个小悬念,那道题的最终解法,不是冒泡排序,而是今天我们要说的 桶排序
啥是桶排序?
我们用教科书的方式说,桶排序就是:
在额外空间充足的情况下,尽量增大桶的数量
使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中
同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。
so,为了大家的脑子着想,我们放弃教科书来用人话解析一下桶排序
桶排序大解析
1.了解桶排序
想知道桶排序,就得理解什么是桶。其实桶就是一个变量,而这个变量有许多个,说人话他们就是一个数组。数组里的每个数或者说每个桶都有一个编号,而桶排序需要的就是这个编号,桶里面有多少水我们不需要知道,我们只需要知道里面是否有水。
我们先将我们要排序的数存进对应编号的的桶内,将桶内装满水,然后再把装水的桶的编号输出,整个排序就完成了。
2.数形结合
如果刚刚还没看懂,我们就来一步一步的解析
我们先取几个数
3 1 6 4 9
然后再定义一个数组(表格里的数字是编号,黑字是没水,红字是有水)
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
一步一步来,先看第一个数3,我们找到编号是3的桶,给他装满水,就是将它设为1
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
再看第二个数1,我们找到编号是1的桶,给他装满水,就是将它设为1
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
以此类推最后的结果是这样的
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
然后我们观察,把有水的桶拿出来,输出它的 编号
注意注意,一定一定输出编号!!!
如果输出数值,也就就是桶里的水,那么输出结果就会是:1 1 1 1 1
不要问我为什么,问就是你给他装水装的是1,不是数值本身,而且开头也说了,我们要的是编号,是桶,不是数值,不是水!!!
看到这个大家应该都理解了,而代码又是什么呢?
3.代码解析
桶排序的代码,要比冒泡排序的简洁多了
int num[1001],number,n,i,j;
先定义一个数组,num,也就是一堆桶,number是一个输入的工具"人",n代表你要输入的数的数量,你要先输入他,i和j是循环的的变量,其实在循环里写也不是不行
cin>>n;
for(i=1;i<=n;i++)
{
cin>>number;
num[number]++;
}
然后先输入n,我们要知道你要输入多少数,然后循环输入n个数number,每次输入都要在num数组里找到编号为number的变量将其设为一
for(i=0;i<1001;i++)
{
for(j=1;j<=num[i];j++){
cout<<i<<endl;
}
}
这里判断有一些不寻常。我没有用if语句,反而我觉得用for循环反而更简便,只是逻辑上的理解有那么亿点难。他把j设为1然后循环继续的条件是j<=num[i],因为num里存的数不是0就是1,也就是说翻译出来就是,num[i]为1就运行cout<<i<<endl;,不是就结束内循环。cout<<i<<endl;这句的意思就是把指定桶的编号输出,连起来就是一个完整的输出了。
#include<iostream>
using namespace std;
int num[1001],number,n,i,j;
int main()
{
cin>>n;
for(i=1;i<=n;i++)
{
cin>>number;
num[number]++;
}
for(i=0;i<1001;i++)
{
for(j=1;j<=num[i];j++){
cout<<i<<endl;
}
}
return 0;
}
这个是总代码
尾声
两个方法有着本质的不同,冒泡排序是一个比较性的排序,而桶排序就是非比较性的排序方法,那么你更偏向于什么方法呢,欢迎在评论区留言,下期给大家再盘一盘还有什么方法能完成排序,那么这期就到这里了,如果喜欢的话请大家点赞收藏家关注,我会持续更新关于C++的各种科普,我们下期再见!
本文由stio工作室出品,请勿转载 ,有什么建议欢迎私信我的邮箱地址:jigehahaha@163.com