算法渣-排序-桶排序

简介: 没有一身好内功,招式再多都是空;算法绝对是防身必备,面试时更是不可或缺;跟着算法渣一起从零学算法

没有一身好内功,招式再多都是空;算法绝对是防身必备,面试时更是不可或缺;跟着算法渣一起从零学算法

线性排序

常见的三种以线性时间运行的算法:计数排序、基数排序和桶排序;网上教程不少,但三者经常混淆,称桶排序但实质可能是计数排序,为了保证原味性,主要参考《算法导论》

需要注意的是线性排序算法是非基于比较的排序算法,都有使用限制才能达到线性排序的效果

定义

桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。

每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。

桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))

算法

桶排序的思想:其实就是先分配再收集的这个一个过程

假设输入是一个随机过程产生的[0,1)区间上均匀分布的实数

把区间划分成n个大小相同的子区间,或称为桶。然后将n个输入元素分布的各个桶中去。先对各个桶中的数进行排序,然后按次序把各桶中的数据列出来即可

    (因为输入元素均匀而独立的分布在区间 [0,1)上,所以不会出现很多数落在一个桶中的情况)

在桶排序算法中,假设输入的是一个含n个元素的数组A,且每个元素满足0≤A[i]<1。另外,还需要一个辅助数组B[0…n-1]来存放链表(桶),并假设可以用某种机制来维护这些表

image.png

刚开始按照示例图的方式理解了桶排序,桶分10个,以十分位为桶号放入各个桶,也算是桶排序一种实现方式,但还是狭隘了


在实际应用时,其实并不然必须元素范围为[0,1),整数,小数都是可以的,只要分布均匀就能最大发挥桶排序优势

优质的桶排序需要考虑几个因素:

  1. 桶的数量:桶越多,占用空间越大
  2. 区间跨度:桶与桶之间的跨度
  3. 桶内元素的排序

一般区间跨度:

除了最后一个桶只包含一个最大值之外,其余各桶之间的区间跨度=(最大值-最小值)/(桶数量-1)

image.png

//伪代码
BUCKET_SORT(A)  
n = length(A)   
for i= 1 to n       
    do insert A[i] into list B   
 for i=0 to n-1       
    do sort list B[i] with insertion sort
 concatenate the list B[0]、B[1],,,B[n-1] together in order

实现

private static void bucketSort(double [] array){
    int bucketNum = 10;//10个桶
    double max = Double.MIN_VALUE;
    double min = Double.MIN_VALUE;
    for (double a:array) {
        if(a> max) {
            max = a;
        }
        if(a<min) {
            min = a;
        }
    }
    //区间跨度
    double span  = (max - min) / (bucketNum - 1);
    double [][]buckets = new double[bucketNum][];
    //初始化桶
    for (int b = 0; b<bucketNum;b++) {
        //以排序元素个数初始化每个桶,以防极端情况
        buckets[b] = new double[array.length];
    }
    //每个桶的元素数量
    int [] index = new int[10];
    for (int d = 0;d<array.length;d++) {
        int bucket =  (int)((array[d] - min)/span);
        buckets[bucket][index[bucket]] = array[d];
        index[bucket]++;
    }
    //每个桶排序,直接使用sort函数了
    for(int b = 0; b<10; b++) {
        Arrays.sort(buckets[b]);
    }
    int j = 0;
    for(int b = 0; b<10; b++) {
        if(index[b] == 0) {
            continue;
        }
        //这儿需要特殊处理一下,主要是因为每个桶初始化了array.length,
        // 经过sort排序,比如第一个桶数组变成了[0.0,0.0,......0.002]
        //需要剔掉数组中的0
        for (int bi = array.length-index[b];bi<array.length;bi++) {
            array[j++] = buckets[b][bi];
        }
    }
}

复杂度

时间复杂度:

假设有m个桶,则每个桶的元素为n/m;

当辅助函数为冒泡排序O(n^2)时,桶排序为 O(n)+mO((n/m)2);

当辅助函数为快速排序时O(nlgn)时,桶排序为 O(n)+m*O(n/m log(n/m))

空间复杂度: 

O(M+N)

通常桶越多,执行效率越快,即省时间,但是桶越多,空间消耗就越大,是一种通过空间换时间的方式


目录
相关文章
|
4月前
|
机器学习/深度学习 算法 安全
【无人机三维路径规划】基于非支配排序的鲸鱼优化算法NSWOA与多目标螳螂搜索算法MOMSA求解无人机三维路径规划研究(Matlab代码实现)
【无人机三维路径规划】基于非支配排序的鲸鱼优化算法NSWOA与多目标螳螂搜索算法MOMSA求解无人机三维路径规划研究(Matlab代码实现)
297 5
|
4月前
|
机器学习/深度学习 运维 算法
基于非支配排序遗传算法NSGAII的综合能源优化调度(Matlab代码实现)
基于非支配排序遗传算法NSGAII的综合能源优化调度(Matlab代码实现)
298 0
基于非支配排序遗传算法NSGAII的综合能源优化调度(Matlab代码实现)
|
5月前
|
机器学习/深度学习 算法 安全
【无人机3D路径规划】基于非支配排序遗传算法NSGAII的无人机3D路径规划研究(Matlab代码实现)
【无人机3D路径规划】基于非支配排序遗传算法NSGAII的无人机3D路径规划研究(Matlab代码实现)
260 1
|
4月前
|
机器学习/深度学习 算法 安全
【无人机三维路径规划】多目标螳螂搜索算法MOMSA与非支配排序的鲸鱼优化算法NSWOA求解无人机三维路径规划研究(Matlab代码实现)
【无人机三维路径规划】多目标螳螂搜索算法MOMSA与非支配排序的鲸鱼优化算法NSWOA求解无人机三维路径规划研究(Matlab代码实现)
204 0
|
4月前
|
机器学习/深度学习 算法 安全
【微电网】【创新点】基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化调度研究(Matlab代码实现)
【微电网】【创新点】基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化调度研究(Matlab代码实现)
158 0
|
5月前
|
机器学习/深度学习 算法 安全
【优化调度】基于matlab非支配排序遗传算法求解车辆充电调度优化问题研究(Matlab代码实现)
【优化调度】基于matlab非支配排序遗传算法求解车辆充电调度优化问题研究(Matlab代码实现)
135 0
|
4月前
|
存储 算法 搜索推荐
软考算法破壁战:从二分查找到堆排序,九大排序核心速通指南
专攻软考高频算法,深度解析二分查找、堆排序、快速排序核心技巧,对比九大排序算法,配套动画与真题,7天掌握45%分值模块。
242 1
软考算法破壁战:从二分查找到堆排序,九大排序核心速通指南
|
4月前
|
供应链 算法 Java
【柔性作业车间调度问题FJSP】基于非支配排序的多目标小龙虾优化算法求解柔性作业车间调度问题FJSP研究(Matlab代码实现)
【柔性作业车间调度问题FJSP】基于非支配排序的多目标小龙虾优化算法求解柔性作业车间调度问题FJSP研究(Matlab代码实现)
187 1
|
4月前
|
机器学习/深度学习 算法 安全
【无人机三维路径规划】基于非支配排序的鱼鹰优化算法NSOOA求解无人机三维路径规划研究(Matlab代码实现)
【无人机三维路径规划】基于非支配排序的鱼鹰优化算法NSOOA求解无人机三维路径规划研究(Matlab代码实现)
127 0
|
5月前
|
传感器 并行计算 算法
【无人机编队】基于非支配排序遗传算法II NSGA-II高效可行的无人机离线集群仿真研究(Matlab代码实现)
【无人机编队】基于非支配排序遗传算法II NSGA-II高效可行的无人机离线集群仿真研究(Matlab代码实现)
357 3