桶排序详解(算法笔记)

桶排序算法

定义:

工作的原理是将数组分到有限数量的桶子里。每个桶子再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)

桶排序是一种非基于比较的排序

算法步骤:

  1. 首先各个元素就可以直接通过整除的方法放至对应桶中,此时右侧所有桶内数据都比左侧的要大
  2. 在刚刚放入桶中的时候,各个桶的大小相对可以确定,右侧都比左侧大,但桶内还是无序的,对各个桶内分别进行排序,
  3. 再依次按照桶间的顺序、桶内序列顺序依次收集,得到一个最终排序的序列。

性能

时间复杂度(说法一,仅仅适用于本blog中的代码):时间复杂度最好可能是线性O(n),O(d * (n + k)),其中k表示桶的数量,n表示数组的大小,d表示序列中最大值的位数,即收集的轮次
空间复杂度:O(N + M),N为临时数组,与待排序列的长度相等,M为桶的数量

另有关于基数排序的时间复杂度公式请查看末尾的链接。
稳定性:桶排序的稳定性取决于桶内排序使用的算法。本blog中的代码使用到的桶内排序的算法是稳定的

实现代码(简单易懂版)

package basic;

import static basic.Insertion_sort.print;

public class Radix_sort {
    public static void main(String[] args) {
        int []arr = {50, 11, 200, 20, 15, 17, 23, 10, 500, 66, 23, 98};
        radix_sort(arr, 0, arr.length - 1, maxBits(arr));
        print(arr);

    }

    // 返回一个数组中的最大值是由几个数字组成的
    public static int maxBits(int arr[])
    {
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < arr.length; i++)
            max = Math.max(max, arr[i]);
        int bits = 0;
        while (max !=0)
        {
            bits++;
            max /= 10;
        }
        return bits;
    }
     // 获取val上第d位(从右往左数)的数字
    public static int getDigit(int val, int d)
    {
        return (val / ((int)Math.pow(10, d - 1))) % 10;
    }


    public static void radix_sort(int[] arr, int L, int R, int digit)
    {
        int i =0, j = 0;
        // 有多少个数就准备多少个桶空间
        int[] buckets = new int[R - L + 1];

        // digit是序列中最大值的位数
        for (int d = 1; d <= digit; d++)
        {
            // 使用10个桶,分别代表0 - 9这9个数字
            int[] counts =  new int[10];
            // 第一步先统计词频
            for (j = L; j <= R; j++)
                counts[getDigit(arr[j], d)]++;

            // 第二步,累加词频
            // counts[0]表明当前位(d位)是0的数字有多少个
            for (j = 1; j < 10; j++)
                counts[j] += counts[j - 1];

            // 出桶,并且将该轮次整理好的数列放到临时数组中
            // 之所以从右到左收集,是为了保证稳定性不被破坏,即符合桶内队列的性质,后进后出
            for (j = R; j >= L; j--)
            {
                // 获取arr[j]的第d位数字
                int number =  getDigit(arr[j], d);
                // 出桶的过程,即将对应的数放到最终合适的位置上
                buckets[counts[number] - 1] = arr[j];
                // 对应digit上的词频减1,表示出桶完毕
                counts[number]--;
            }
            // 将临时数组中的数据放到arr中,以便进行下一轮的入桶操作
            for (i = L, j =0; i <= R; j++, i++)
                arr[i] = buckets[j];
        }
    }

}


这篇博客讲解的比较详细,建议点击此链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值