左神桶排序和基数排序

桶排序

  • 计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。计数排序不是比较排序,所以他优于任何比较排序。

  • 我们将一个数组所有数字出现的次数,统计出来,放入一个辅助数组中,然后把辅助数组中统计的数组从小到大,按每个数出现的次数,有几次输出几次就可以得到一个有序的序列。
    在这里插入图片描述
    图源:https://www.runoob.com/w3cnote/counting-sort.html

例如: 给定一组学生年龄数组,要求给该数组进行计数排序,我们知道年龄的范围是0~200之间,
在这里插入图片描述
以下给出python语言的排序代码:

def countingSort(arr,maxValue):
{
	#桶的长度是数组中数字最大的数的数值
    bucketlen=maxValue+1
    #将桶内数组全部置零 用于统计出现次数
    bucket = [0]*bucketlen
    sorttedIndex=0
    arrLen=len(arr)
    for i in range(arrlen):
        if not bucket[arr[i]]:
            bucket[arr[i]]=0
        bucket[arr[i]]+=1
    for j in range(bucketlen):
        while bucket[j]>0:
            arr[sorttedIndex]=j
            sorttedIndex+=1
            bucket[j]-=1
    return arr   
}

基数排序

  • 基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
    在这里插入图片描述
    图源:https://www.runoob.com/w3cnote/radix-sort.html

思考: 准备10个队列(0~9),将每个数字从个位开始,依次放在相应位置上,并且一个“桶中”如果有多个数字,就按先入先出的原则将每个数输出,这样就保证的这一位上的数字依然是从小到大有序的,进而将这种有序性一直传递了下去。

代码算法

利用了一个极其精巧的方式,可以不需要队列完成先入先出的操作。理解起来还是有一点难度的,如下图解释:

以下是以个位数为基准的一次排序过程,完整的过程是分别对个位、十位、百位进行如下的操作:
在这里插入图片描述在这里插入图片描述

在这里插入图片描述
Java语言描述的代码如下:

//arr[L...R]排序 digit是最大的数字有多少个十进制位,
//也就是最大值的数 位数
public static radixSort(int[] arr,int L,int R,int digit)
{
    final int radix=10;
    int i=0,j=0;
    //有多少个数准备多少个辅助空间
    int[] bucket=new int[R-L+1];
    //有多少位就操作几次
    for(int d=1;d<=digit;d++)
    {


        int[] count=new int[radix];

        for(i=L;i<=R;i++)
        {
            //得到倒数第d位上的数字是几
            j=getDigit(arr[i],d);
            count[j]++;
        }
        //创建count‘数组,count[0]上的数字不变
        for(i=1;i<radix;i++)
            count[i]=count[i]+count[i-1];

        //从右向左遍历arr数组
        for(i=R;i>=L;i--)
        {
            j=getDigit(arr[i],d);
            bucket[arr[j]-1]=arr[i];
            count[j]--;
        }

        //把某一位有序的数组copy回原数组
        for(i=L,j=0;i<=R;i++,j++)
        {
            arr[i]=bucket[j];
        }


    }
}

//返回x这个数在倒数第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 i=0;i<arr.length;i++)
    {
        max=Math.max(max,arr[i]);
    }
    int res=0;
    while(max!=0){
        res++;
        max/=10;
    }
    return res;
}

public static void main()
{
    int[] arr={022,021,032,001,100}
    if(arr==null||arr.length<2){
        return;
    }
    radixSort(arr,0,arr.length-1,maxbits(arr));
}

时间复杂度

O( log(10,max)*N )
max有log(10,max)个十进制位,所以遍历了log(10,max)次数组,数组中共有N个数字。
在计算机中,十进制位有限,所以时间复杂度为O(N)。

不基于比较的排序时间复杂度很小,但是应用的范围很有限。基于排序的比较是比较实用的,应用范围较广。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值