C++桶排序——详解

前言:现在中小学学习C++的人越来越多,可网上搜了搜桶排序的博文,发现大家都写得好深奥,于是,便有了这篇简单易懂(不是)的桶排序文章

 

思考一下,你面前有一些不大的数字,但是它们是乱序的,请问你如何将它们排成有序的序列?

 不妨,让我们把这些数字当成生活中常见的东西,比如,这些都是不同种类的垃圾编号,我们要将这些垃圾进行分类摆放整齐,那自然的,我们需要有一些垃圾桶

可以发现,这些垃圾的编号种类不是很多,最小是1,最大是7,那么我们最多只需要准备7个垃圾桶就可以了,编号为1到7

 

接下来,就是把每个垃圾丢到对应的垃圾桶中就可以了,然后每一个垃圾桶,就统计有多少个垃圾被丢到了这里面

 

 

 

 

 

 

 

 

 

 

 以上就是将垃圾丢进垃圾桶的过程了,让我们回到编程中来分析一下这个过程中,我们得到了哪些数据

首先,很明显垃圾丢进垃圾桶的过程,是从左到右将垃圾依次丢入的,这符合循环的重复执行概念,所以这个过程是在循环里实现的

然后,对于循环里每一个垃圾的数值,我们设定为x; 

其次,很明显我们有7个连续的垃圾桶排放在一期,这符合数组的定义,所以我们将这7个垃圾桶定义为数组,int vis[8],下标从1到7

思考垃圾丢进垃圾桶之前,桶应该都为空,所以vis数组应该初始化为0,表示初始时任何一个垃圾桶都没有垃圾

思考垃圾丢进垃圾桶过程中,桶里面的数字会 + 1,表示这个垃圾桶多了一个垃圾,用代码表示可以写成 vis[x] = vis[x] + 1;意为x号垃圾桶的垃圾数量加1

int main()
{
    int vis[8] = {},x,n;//vis[i]:i出现的次数 
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> x;
        vis[x]++; //x出现的次数 + 1 
    }
    return 0;
}

 

现在,让我们考虑一下按垃圾桶的顺序,依次将桶里面的垃圾全部取出,看看能不能实现排序的效果

①:vis[1] = 2,说明1号垃圾有两个,我们要取出两个1

 ②:vis[2] = 2,说明2号垃圾有两个,我们要取出两个2

③:vis[3] = 0,说明3号垃圾没出现,那就不必理会

④:vis[4] = 2,说明4号垃圾桶有两个垃圾,那就要取出两次4

 ⑤:vis[5] = 1,说明5号垃圾桶有一个垃圾,那就要取出一次5

 

⑥:vis[6] = 0,说明6号垃圾没出现,那就不必理会

⑦:vis[7] = 1,说明7号垃圾桶有一个垃圾,那就要取出一次7

 

最后,来看一下程序取出桶里数字的过程

for(int i = 1; i <= 8; i++)
{
    while(vis[i] >= 1)
    {
        cout << i << " ";
        vis[i]--; //取出i,减少i出现的次数 
    }
}

输入:

8

1 4 1 5 2 5 2 7

输出:

1 1 2 2 4 5 5 7

完整代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int vis[8] = {},x,n;//vis[i]:i出现的次数 
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> x;
        vis[x]++; //x出现的次数 + 1 
    }
    for(int i = 1; i <= 7; i++) //桶的编号是1到7
    {
        while(vis[i] >= 1)
        {
            cout << i << " ";
            vis[i]--; //取出i,减少i出现的次数 
        }
    }
    return 0;
}

 

 

细节问题:

1.可以发现在桶存储数据的过程中出现了空桶,说明会有空间浪费的情况出现,如果在n个数据中,有数据x出现大小超过1e7(1千万),就意味着我们要准备超过1e7个桶,这样会严重浪费系统内存,因此,桶排序只适合出现的数据都被限制在比较小的范围内的时候使用,例如最大不超过1e5或1e6

2.桶排序的时间复杂度,可以发现我们只需要一次循环n个数,就可以将每个数丢到桶里,说明这个算法只需要一重循环可以实现,对于一重循环n个数的程序,我们称其时间复杂度为O(n),但是别忘了,桶的数量不一定是n个,设桶的数量为k个,那么在取出桶的过程中也是一个1到k的循环,为O(k),所以整体的时间复杂度为O(n + k),还是比较快速的

 

posted @ 2024-06-13 16:01  CRt0729  阅读(251)  评论(0编辑  收藏  举报