基数排序

来源:互联网 发布:时时彩搭建源码 编辑:程序博客网 时间:2024/06/05 16:21

基本思想

将待排数据中的每组关键字依次进行桶分配。
实质是一种考虑多关键字的排序算法。

MSD:

假设我们有一些二元组(a,b),如果我们对a为首要关键字,b为次要关键字进行排序。就称为MSD
我们按照首要关键字排序,把相同的分到一起,这样我们就有了若干个桶,然后再按照次要关键字分别对每一堆进行排序。最后合并,这就是MSD

LSD

从最低有效关键字开始排序。具体看下面:

具体示例:

278、109、063、930、589、184、505、269、008、083

我们将每个数值的个位,十位,百位分成三个关键字: 278 -> k1(个位)=8,k2(十位)=7,k3=(百位)=2。

然后从最低位个位开始(LSD),对所有数据的k1关键字进行桶分配(因为,每个数字都是 0-9的,因此桶大小为10),再依次输出桶中的数据得到下面的序列。

实际我们要先建立桶(LinkedList):(根据最低位)

0 1 2 3 4 5 6 7 8 9 930 063 184 505 278 109 083 008 589 269

输出为:

930、063、083、184、505、278、008、109、589、269

再对上面的序列接着进行针对k2的桶分配:

0 1 2 3 4 5 6 7 8 9 505 930 063 278 083 008 269 184 109 589

输出序列为:

505、008、109、930、063、269、278、083、184、589

最后针对k3的桶分配,(最高位)

0 1 2 3 4 5 6 7 8 9 008 109 269 505 930 063 184 278 589 083

输出序列为:

008、063、083、109、184、269、278、505、589、930

LSD算法实现

    public int getDigit(int x,int d){        int a[]={1,10,100,1000};        return (x/a[d])%10;    }    //按照数据来定义k进制/每位出现的可能性    //3位数,还是需要观察,这对输入数据有要求,我要检测这个数据是多少位?    public void Sort(int[] A){        int N=A.length, k=10,P=3; //需要观察数据        int[] tmp=new int[N];        int[] count=new int[k];//桶 初始化值应该为0        for(int d=0;d<P;d++){            //每次循环要对count清空            for(int j=0;j<N;j++)                count[j]=0;            //统计入每个桶的元素个数            for(int j=0;j<N;j++){                int i=getDigit(A[j],d);                count[i]++;            }            //算下标, 算出真正对应 A数组的下标            for(int j=1;j<k;j++){                count[j]+=count[j-1];            }            //数据依次转入桶中            //必须倒序存进来才对            for(int j=N-1;j>=0;j--){                int i=getDigit(A[j],d);                //index = count[i]-1;                if(count[i]<1)                    continue;                tmp[count[i]-1]=A[j];//放入临时数组                count[i]--; //对应桶的数据索引减一            }            for(int j=0;j<N;j++){                A[j]=tmp[j];            }        }    }

基数排序还可以用于多关键字排序

例如对扑克牌排序的问题

主位优先排序MSD

思想
我们可以根据花色建立4个桶,然后将52张牌分别放入这4个桶,然后对这4个桶分别排序。 当然我们可能需要调用快排或者其他比较排序算法。
最后把它们合并就可以了。

LSD解决

为次关键字也就是面值建立13个桶,结果因为扑克牌就只有13种值,故其实我们分配到13个桶之后就已经排好序了。

实质来说,当主位的基数个数大于次位的时候,主位优先更快。

效率分析

设元素个数为N,整数进制为B,LSD的趟数为P(也就是我们的位数),则最坏的时间复杂度是:
O(P(N+B))
因为每一趟我们要收集分配这些数到我们的桶中,其实对于每一趟来说,我们做的事情和桶排序是一样的。(因为我们不需要对桶里面的内容进行排序,而仅仅是分配)
基数排序的空间复杂度是
O(M+N) M为桶的数量。

0 0
原创粉丝点击