基本排序算法 之九 ——桶排序

 


基本排序算法总结与对比 之九  ——桶排序 


1、桶排序

       桶排序是对基数排序的演绎。计数排序是一个萝卜(相同的数)一个坑,而桶排序是几个萝卜(一定范围的数)一个筐。桶排序是将数据分到有限个桶中,然后对每个桶中的数据再排序(可能继续用桶排序,也可能用其他的排序方法)。

       那么要解决的问题是:

       ① 怎么划分桶?即 数据该划分为几个范围(分几个桶的问题),范围又要划分多大(分多大桶的问题)。

       ② 怎么实现桶?即 用什么容器来储存数。(链表,数组,甚至STL中的容器 都可以)。

       ③ 桶中的数据再排序用什么排序方法。(相机抉择吧)

       解决问题:

       ① 按照常见的一种方式,桶中数据的 范围 =(最大数 - 最小数 + 1)/ 桶的数量 。这种方法适用于数据分布比较均匀的数列,本文就采取这种方法。 还有其他的划分方式,比如前面的桶范围都一样,但最后一个桶范围特别大,适用于加数递增的数列,等等。

       ② 本文就选择 vector 作为容器,主要为了表示桶排序的思想。

       ③ 桶里面就使用std::sort()排序吧。

       

       排序过程解读:

       ① 找出数列中 最大,最小的数。

       ② 创建若干个桶;桶的范围则由:范围 =(最大数 - 最小数 + 1)/ 桶的数量 算出,范围取double,否则可能因为计算误差导致数据选择错误的桶,甚至可能选取一个不存在的桶 的编号 而造成程序崩溃。

       ③ 遍历待排序数组,将数据放进对应的桶;数据arr[k]桶的编号 的映射关系为: 桶的编号 = (arr[k] - 最小数)/ 范围 ,显然数值越大,所在桶的编号越大。

       ④ 分别对每个桶内的数据排序。

       ⑤ 依次从桶中取出数据放回原数组。

 

       代码如下:

#include <vector>    //用 vector 做桶

//找出最大数
template<typename T>
T findMax(T arr[], int lo, int hi)
{
    T maxNum = *(arr + lo);
    while(++lo < hi)
    {
        if(*(arr + lo) > maxNum) maxNum = *(arr + lo);
    }
    return maxNum;
}

//找出最小数
template<typename T>
T findMin(T arr[], int lo, int hi)
{
    T minNum = *(arr + lo);
    while(++lo < hi)
    {
        if(*(arr + lo) < minNum) minNum = *(arr + lo);
    }
    return minNum;
}

template<typename T>
void bucketSort(T arr[], int lo, int hi)
{
    T maxNum = findMax(arr, lo, hi);
    T minNum = findMin(arr, lo, hi);

    std::vector<T> *buckets = new std::vector<T>[10];  //放有10个vector的数组
    double range = (maxNum - minNum + 1) / 10.0;    //随便分,这里分10个桶,注意范围取浮点数
    
    for(int i = lo; i < hi; i++)
    {
        buckets[(int)((arr[i] - minNum) / range)].push_back(arr[i]);  //对应范围的数放进桶里面
    }

    T *p = arr + lo;
    for(int i = 0; i < 10; i++)
    {
        std::sort(buckets[i].begin(), buckets[i].end());    //对桶里的数排序
        for(auto x : buckets[i])
        {
            *(arr++) = x;
        }
    }

    delete [] buckets;

}

       上述桶排序的时间复杂度:

       设 有M个桶,N个数,桶内排序方法的复杂度为O(nlogn):对于N个数,M个桶 则为N(log2N - log2M),将数据分类放进桶中复杂度为N;数据从桶中放回数组又为N。总共为O(2N+N(logN-logM))。

       桶排序本身的排序思维是稳定的,若桶内采用的排序算法依然稳定,则整个算法是稳定的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值