这才是你想要桶排序

Posted 嵌入式Linux

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了这才是你想要桶排序相关的知识,希望对你有一定的参考价值。

这才是你想要桶排序

这才是你想要桶排序

前面说的

昨天发的桶排序文章,有同学回复,确实有比较精明的同学,文章就是想提出一个比较简单的思路,本来想给自己的排序方式写个名字叫做“木桶排序”,这篇文章讲解真正的桶排序,结合前面的文章,希望看完后对桶排序理解更加深刻。

这才是你想要桶排序

桶排序定义

桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。
重点:前面的文章说,有多少数据就需要多少桶,但是实际上发明桶排序的人对桶的要求是非常有限的,这就是差别。

这才是你想要桶排序


举个例子

这才是你想要桶排序

接上面的阿布老师~~
阿布老师安排同学们考试结束后,接到教学主任的通知需要马上把同学们的分数统计并做好排序,但是他来到教室,发现教室后面只有5个垃圾桶,阿布老师冥思苦想,要用这几个垃圾桶怎么把同学们的分数给排名出来呢?

  • 首先还是给垃圾桶标号,这个还是不能少的。

  • 约定,1号垃圾桶放分数是1-20的同学的成绩单,2号垃圾桶放分数是20-40的同学的成绩单,3号垃圾桶放分数是40-60的同学的成绩单,4号垃圾桶放分数是60-80的同学的成绩单,5号垃圾桶放分数是80-100的同学的成绩单

  • 当向同一个垃圾桶放入新数据的时候,先判断桶中最高分成绩和新放入成绩的大小,如果比原来最高分还高,则把新插入成绩放在原来成绩的后面。

  • 否则,把放入的新的成绩单与原来的成绩单从后往前依次比较,如果存在的成绩大于新放入的成绩,则存在的成绩往后挪一个位置,循环比较已存放的所有成绩单,如第一个桶已经有了63,再插入51,67后,桶中的排序为(51,63,67)一般通过链表来存放桶中数据

  • 阿布老师依次从1~5号桶捡起自己扔进来的成绩单,(然后依次输出所有(非空)桶里面的数据)最后完成排序输出

  • 阿布赶紧拿出NBA视频看看10佳球,表扬自己堪比爱因斯坦的智商。

可以认为里面有5个大桶,每个大桶都分别代表一定的数据范围

这才是你想要桶排序

然后再对大桶里面的数据进行排序,这时候可以使用冒泡排序或者插入排序,最后应该是变成这样的

这才是你想要桶排序

代码举例

/*************************************************************************
    > File Name: 1.c
    > Author: 
    > Mail: 
    > Created Time: Mon 07 Jan 2019 02:11:36 PM CST
 ************************************************************************/


#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define random_set(a,b) ((rand()%(b-a))+a)//获取a~b范围内的随机数
#define N 5 //用来做桶排序的桶数量
#define M 20 //定义二维数组的长度

int main(void)
{

    int array_stu[50];//用来保存每个同学的分数
    int array_out[N][M]; //用来保存排序后的数据 ,有限的桶数量,跟之前的不同
    int max=0,min=0;  //分数的最大最小值,用来做中间变量
    int mid=0;//中间变量,用来区分每个桶里面存放的数据间隔

    srand((int)time(NULL));//设置随机数的基准,这样保证每次的运行结果不同

    /*先初始化两个数组*/
    memset(array_stu, 0, sizeof(array_stu));
    memset(array_out, 0, sizeof(array_out));

    /*初始化最大最小值*/
    max = 100;
    min = 1;
    /*用程序随机数给50个学生打分*/
    for(int i=0;i<50;i++)
    {
        array_stu[i] = random_set(min,max);
    }

    printf("max:%d min:%d M:%d ",max,min,M);

    /*把50个学生的分数分别扔到对应的桶里面去*/
    for(int i=0;i<50;i++)
    {
        /*每个箱子的尾部*/
        static int index0=0,index1=0,index2=0,index3=0,index4=0;
        /*遍历原来的数据*/
        static int temp2 = 0,temp3 = 0,temp4 = 0,temp1=0;

        /*用来确定数据的位置*/
        int position = (array_stu[i] / M);
        if(position < 0)
            position = 0;
        //printf("array_stu[i] %d position:%d ",array_stu[i],position);


        if(position ==0)
        {
            temp2 = index0++;
        }
        else if(position ==1)
        {
            temp2 = index1++;
        }
        else if(position ==2)
        {
            temp2 = index2++;
        }
        else if(position ==3)
        {
            temp2 = index3++;
        }
        else
        {
            temp2 = index4++;
        }
        temp1 = temp2 -1;
        if(temp1 <0)
            temp1 =0;
        //printf("array_stu[i] %d array_out[%d][%d]:%d ",array_stu[i],position,temp2,array_out[position][temp2]);
        /*如果大于前面的数据就要到数组后面去*/
        if(array_stu[i] >= array_out[position][temp1])
        {
            /*直接在最后面插入最大的数据*/
            array_out[position][temp1+1] = array_stu[i];
        }
        else
        {
            while(temp2 >0)
            {
                if(array_out[position][temp2] >array_stu[i])
                {
                    array_out[position][temp2 +1] = array_out[position][temp2];
                    /*保存这个中间的位置,空出来,放比他小的数据*/
                    temp3 = temp2;
                }
                temp2 --;
            }
            array_out[position][temp3] = array_stu[i];

        }
    }

    /*把排序后的数据输出*/
    for(int i=0;i<N;i++)
    {
        /*有些同学的分数是一样的*/
        for(int j=0;j<M;j++ )
        {
            if(array_out[i][j]> 0)
                printf("%d ",array_out[i][j]);
        }
    }

    return (0);
}

输出结果

max:100 min:1 M:20
1
3
8
8
11
19
19
21
21
23
28
30
32
36
37
39
40
41
43
43
47
47
55
55
57
58
58
60
60
67
69
70
74
78
79
83
86
89
90
91
91
98
98
99
99

算法复杂度

第一个排序的for循环,复杂度是O(N),但是下面还有一个while(n--),所以有必要说明一下最好复杂度和最坏复杂度。

  • 最好复杂度:就是放入垃圾桶的成绩单都比原来最大的成绩单大,每次都直接放到原来成绩单的后面,这样while代码就没跑,复杂度就是O(N)。

  • 最坏复杂度:就是放入垃圾桶的成绩单都比原来最大的成绩小,这样就需要遍历原来的成绩单数组给它找个合适的位置,加上前面的O(NN/5)等于O(N*N)等于O(N^2)



觉得不错,请帮忙转发点好看,您的每一次支持,我都将铭记于心






以上是关于这才是你想要桶排序的主要内容,如果未能解决你的问题,请参考以下文章

这才是你的归属

这才是你需要的高效在线PDF转换平台

C/C++学习路线:这才是你需要的C语言C++学习路线

C/C++编程这才是你最需要的C语言C++学习路线

这才是选择排序正确的打开方式

Guava RateLimiter 实现 API 限流,这才是正确的姿势!