算法学习笔记--桶排序

桶排序

算法原理

介绍

桶排序(Bucket sort)或 箱排序,原理是将数组分到有限数量的桶里, 然后对每个桶分别排序(可能使用别的排序算法或已递归方式继续使用桶排序进行排序),最后将各个桶的数据有序地合并起来。

假设一组数据,arr = [2, 1, 7, 0, 3, 4, 5, 9, 6, 8];
使用冒泡排序, 所需时间为: 102=100
使用桶排序,将10条数据分到两个桶子里: bucket1 = [2,1,0,3,4], bucket2 = [7,5,9,6,8]
分别使用冒泡排序,所需时间为 52+52=50

排序过程
  1. 设置一个定量的数组当做空桶子
  2. 遍历数组,把每个元素放到对应的桶子里去
  3. 对每个不是的空桶子进行排序
  4. 从不是空的桶子里把元素再放回原来的数组中

查看分步动画演示

性能

N个待排数据, M个桶
平均每个桶[N/M]个数据的桶排序平均时间复杂度为:
O(N)+O(M*(N/M)*log(N/M))=O(N+N*(logN-logM))=O(N+N*logN-N*logM)
设: K=N*(logN-logM)

  • 平均时间复杂度 O(N + k)
  • 空间复杂度 O(N + M)
  • 最差时间复杂度 O(N ^ 2)

当N=M时, 极限情况下每个桶只有一个数据时,桶排序的最好效率能达到O(N)

应用

  1. 对500W个考生的分数进行排名
    • 分析: 如果使用快排,平均比较次数为O(5E6 * log5E6)≈1.112E8.但是
      我们发现这些数据有特殊的条件:100<=score<=900.那么我们就可以考虑使用桶排序
    • 方法:创建801(100 ~ 900)个桶,将每个考生的分数丢进f(score) = score - 100的桶中,
      从头到尾遍历一遍数据仅需500W次,然后根据桶号大小依次将桶中数值输出,
      就可以得到一个有序的序列,而且可以很容易的到每个分数对应的考生数。
  2. 在一个文件中有10G整数,乱序排列,要求找出中位数。内存限制为 2G。
    • 分析
    • 思想
    • 方法

局限

  • 不适合元素值集合很大的情况

程序实现

Javascript 实现
class Node{
    constructor(value, next){
        this.value = value;
        this.next = next;
    }
    toString(){
        var array = [];
        var node = this;
        while(node){
            array.push(node.value);
            node = node.next;
        }
        return array.join("->");
    }
}
function insert(head, value){
    if(!head){
        return new Node(value);
    }
    if(value < head.value){
        return new Node(value, head);
    }
    var node = head;
    while(node){
        var next = node.next;
        if(!next){
            node.next = new Node(value);
            break;
        }else if(next.value > value){
            node.next = new Node(value, node.next);
            break;
        }else{
            node = next;
        }
    }
    return head;
}
function merge(bucket, array, order){
    if(!order){
        order = "asc";
    }
    var elementIndex;
    var step;

    if(order === "desc"){
        elementIndex = array.length - 1;
        step = -1;
    }else{
        elementIndex = 0;
        step = 1;
    }

    bucket.forEach(node => {
        while(node){
            array[elementIndex] = node.value;
            elementIndex += step;
            node = node.next;
        }
    });
}
function bucketSort(array, order){
    if(!array || array.length < 2){
        return array;
    }
    var bucket = [],
        numberOfElements = array.length,
        maximumArrayValue = Math.max.apply(Math, array)
        minimumArrayValue = Math.min.apply(Math, array),
        ratio = numberOfElements / (maximumArrayValue - minimumArrayValue + 1);

    bucket.length = numberOfElements;

    array.forEach(value => {
        var index = Math.floor((value - minimumArrayValue) * ratio);
        var head = bucket[index];
        // 按大小顺序插入到桶中
        bucket[index] = insert(head, value);
    });
    // 合并结果
    merge(bucket, array, order);
    return array;
}
Java 实现
public void bucketSort(int[] array){

}
Python 实现
def bucketSort():
    pass;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值