基数排序算法的简单编写

基数算法

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。基数排序的发明可以追溯到 1887 年赫尔曼·何乐礼在打孔卡片制表机 (Tabulation Machine)上的贡献。

排序过程:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

基数排序法会使用到桶,顾名思义,通过将要比较的位(个位、十位、百位...),将要排序的元素分配到0~9个桶中,借以达到排序的作用,在某些时候,基数排序法的效率高于其它的比较性排序法。

算法步骤

基数排序的方式可以采用 LSD (Least sgnificant digital) 或 MSD (Most sgnificant digital),LSD 的排序方式由键值的最右边开始,而 MSD 则相反,由键值的最左边开始。 以 LSD 为例,假设原来有一串数值如下所示:

36   9   0   25   1   49   64   16   81   4

首先根据个位数的数值,按照个位值等于桶编号的方式,将它们分配至编号0至9的桶子中:

编号0123456789
 01  642536  9
  81  4 16  49

然后,将这些数字按照桶以及桶内部的排序连接起来:

0   1   81   64   4   25   36   16   9   49

接着按照十位的数值,分别对号入座:

编号0123456789
 016253649 64 81 
 1         
 4         
 9         

最后按照次序重现连接,完成排序:

0   1   4   9   16   25   36   49   64   81


效率分析

基数排序的时间复杂度是O(k * n),其中n是排序元素个数,k是数字位数。注意这不是说这个时间复杂度一定优于O(n * log(n) )k的大小取决于数字位的选择(比如比特位数),和待排序数据所属数据类型的全集大小;k决定了进行多少轮处理,而n是每轮处理的操作数目。

以排序n个不同整数来举例,假定这些整数以B为底,这样每位数都有B个不同的数字,k = logBNN是待排序数据类型全集的势。虽然有B个不同的数字,需要B个不同的桶,但在每一轮处理中,判断每个待排序数据项只需要一次计算确定对应数位的值,因此在每一轮处理的时候都需要平均n次操作来把整数放到合适的桶中去,所以就有:k ≈ logBN ,所以,基数排序的平均时间$T$就是:T ≈ LogB(N) * n其中前一项是一个与输入数据无关的常数,当然该项不一定小于log n

如果考虑和比较排序进行对照,基数排序的形式复杂度虽然不一定更小,但由于不进行比较,因此其基本操作的代价较小,而且在适当选择的$B$之下,k一般不大于log n,所以基数排序一般要快过基于比较的排序,比如快速排序。


算法稳定性

基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优 先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。


动图演示







20170122084056_983.gif

简单的代码实现

<?php
/**
  *基数排序 又称桶子排序
  */
 //定义数组
     $arr=[2,358,236,147,5,652,431,963,864,3569,4125,188,214,652,398,564,268];
 //定义数组,十个桶子
     $sort=[];
 //创建十个桶 把下标作为桶号
     for ($i=0; $i <=9 ; $i++) {
         $sort[$i]=[];
     }

     //获取数组的长度
     $count=count($arr);  
     //获取数组中最大的值
     $max=max($arr);
    //统计最大值有多少位
    $len=strlen($max);
    //循环把对应桶子的数放入对应的桶子中
    for ($i=0; $i < $len ; $i++) {
        //计算基数
        $exp=pow(10,$i);  //php  pow(x,y) pow函数返回x的y次方
        //放入桶子中
        for ($j=0; $j < $count ; $j++) {
            $num=($arr[$j]/$exp)%10; //求出所对应的位数上的数
            $sort[$num][]=$arr[$j]; //放入桶内
        }
        //把分好的桶子里的数接着连起来进行下一位的比较
        $arr=[]; //先把数组清空 然后把待排好的数组放入$arr中
        foreach ($sort as $k => $v) {
            //直接把sort的值按照顺序放入arr中
            $arr=array_merge($arr,$v);
            $sort[$k]=[];
        }
    }
   echo "<pre>";
   print_r($arr);

 ?>

以上代码为非专业人士编写,仅供参考和批评,谢谢

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值