桶排及稳定性汇总


前言

桶排序及其应用


一、桶排序流程

相比其它排序,桶排序不基于比较的排序,根据数据状况来排序。应用范围不是很广。

(1)计数排序

定义一个数组,用来记录每个数出现的次数,数组下标就是值,然后根据排序规则,分别输出每种数的个数。最终就得到有序数组。

代码如下:

public class countSort {
    public static void main(String[] args) {
        int []arr={21,1,8,15,15,15,1,1,2,2,3,4,4,4,4};
        System.out.println("排序前:"+Arrays.toString(arr));
        countSort(arr);
        System.out.println("排序后:"+Arrays.toString(arr));
    }
    public static void countSort(int[]arr){
        int max=maxNum(arr);// 最大数
        int[]help=new int[max+1];// 创建出最大数长度的辅助数组
        for (int i=0;i<arr.length;i++){
            help[arr[i]]+=1;// 计数
        }
        System.out.println("桶子:"+Arrays.toString(help));
        int temp=0;
        for (int j=0;j<help.length;j++){// 出桶
            if (help[j]!=0){
                for (int d=0;d<help[j];d++){
                    arr[temp++]=j;
                }
            }
        }
    }
    // 找最大数
    public static int maxNum(int []arr){
        int max=0;
        for (int i:arr){
            max=Math.max(max,i);
        }
        return max;
    }
}


时间复杂度:O(N)
结果如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/2ebd86fbfe2e4e97b0bcda10696f326d.png

(2)基数排序

准备十个桶,分别对应数字0~9,桶就是个容器,可以是队列,数组,栈等…,最开始将所有数按最多位的数以0补齐位数(【34,789,444】补全为:【034,789,444】),从个位数将数放入对应桶中(034就放入4号桶,789就放入9号桶),然后依次从0 ~ 9号桶的顺序取出一个桶里的遵循先进先出。然后从十位重复,最后到最高位,出桶后就得到有序数组。(优先级是从最高位开始依次递减)。

代码如下:

public class radixSort {
    public static void main(String[] args) {
        int []arr={63,21,80,91,23,42,444,382,45};
        System.out.println("排序前:"+ Arrays.toString(arr));
        radixSort(arr);
        System.out.println("排序后:"+Arrays.toString(arr));
    }
    public static void radixSort(int []arr){
        if (arr==null||arr.length<2){
            return;
        }
        radixSort(arr,0,arr.length-1,maxbits(arr));
    }
    public static void radixSort(int []arr,int L,int R,int maxBit){
        final int radix=10;// 10个桶子
        int i=0,j=0;// j=>当前数的第几位
        int []bucket=new int[R-L+1];// 辅助数组
        for (int d=1;d<=maxBit;d++){ // 有多少位就进多少次
            // 桶子共有maxBit个
            // 桶子的计数与流程有差别,桶子计数的为小于等于当前下标的个数之和
            // (第6个桶子是【0,1,2,3,4,5,6,7】的数字的总和)
            int []count =new int [radix];
            for (i=L;i<=R;i++){// 取出当前位的数字 入桶
                j=getDigit(arr[i],d);
                count[j]++;
            }
            for (i=1;i<radix;i++){// 桶子的累加和
                count[i]=count[i]+count[i-1];
            }
            for (i=R;i>=L;i--){// 从右到左遍历,取出对应位 桶中对应数--,摆放位置 出桶
                j=getDigit(arr[i],d);
                bucket[count[j]-1]=arr[i];
                count[j]--;
            }
            for (i=L,j=0;i<=R;i++,j++){// 将辅助数中的值给arr准备下一次进桶出桶
                arr[i]=bucket[j];
            }
        }
    }
    // 取出一个数中的第d位数字
    public static int getDigit(int x,int d){
        return ((x/(int)(Math.pow(10,d-1)))%10);
    }
    // 找一个数组内最多有多少位
    public static int maxbits(int []arr){
        int max=Integer.MIN_VALUE;
        for (int j : arr) {// 找出最大值
            max = Math.max(max, j);
        }
        int res=0;
        while (max!=0){// 循环计位数
            res++;
            max/=10;
        }
        return res;
    }
}

结果如下:

在这里插入图片描述

二、排序算法的稳定性及其汇总

稳定性

同样的个体间,如果不因为排序而改变相对次序,就是这个排序是有稳定性的;否则就没有。

  1. 不具备稳定性的排序:
  • 选择排序
  • 快速排序
  • 堆排序
  1. 具备稳定性的排序:
  • 冒泡排序
  • 插入排序
  • 归并排序
  • 一切桶排序思想下的排序

目前按没有找到时间复杂度O(N*logN),空间复杂度O(1)又稳定的排序算法。

时间复杂度额外空间复杂度稳定性
选择O(N^2)O(1)×
冒泡O(N^2)O(1)
插入O(N^2)O(1)
归并O(N*logN)O(N)
快排(随机)O(N*logN)O(logN)×
O(N*logN)O(1)×

  • 归并排序的额外空间复杂度可以变成O(1)但会丧失稳定性,而且非常难(归并排序,内部缓存法)
  • 原地归并排序,让时间复杂度变成O(N^2)
  • 快速排序可以做到稳定,但空间复杂度会变为O(N),而且非常难
  • 目前没有找到时间复杂度O(N*logN),额外空间按复杂度O(1),又稳定的排序。
  • 奇数放在数组左边,偶数放在数组右边,还要求原始的相对次序不变。

工程上堆排序的改进

  • 充分利用O(N*logN)和O(N^2)排序各自优势
    在快排中,当样本容量小于60时使用插入排序更快(综合排序)

  • 稳定性考虑
    在系统中使用排序,基础类型,系统会使用快排进行排序;而遇到非基础类型排序时,会使用归并保持稳定性。

总结

以上就是桶排序的所有内容。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天将降大任于我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值