基数排序(桶排序)

来源:互联网 发布:网络贸易 编辑:程序博客网 时间:2024/05/16 05:12

基数排序又称桶排序,它不直接比较关键字的大小,而是比较关键字中各位的值来实现排序的。
假设关键字从高位到低位可以由k1、k2、……、kd构成。
最高位优先(MSD)法:先按k1排序分组,再对各组按k2排序分组,直到按最次位kd分组后,再将各组连接起来,便得到一个有序序列。
最低位优先(LSD)法:先从kd开始分组,再对kd-1进行排序,直到对k1分组后得到一个有序序列。

1. 二进制快速排序

按关键字的最高位对文件进行划分,接着递归地对子文件进行排序。变量w记录正被检查的位。从0(最高位)开始,当i=j时,划分结束。这时,a[i]右边所有的元素第w位都是1,而a[i]左边所有元素第w位的值是0。

#define digit(A,B) A[B]quicksortB(int a[],int l,int r,int w){    int i=l,j=r;    if(r<=l || w>bitword) return;    while(j!=i)    {        while(digit(a[i],w) == 0 && (i<j)) i++;        while(digit(a[j],w) == 1 && (i<j)) j--;             exch(a[i],a[j]);    }    if(digit(a[r],w)==0) j++;    quicksortB(a,l,j-1,w+1);}void sort(Item a[],int l,int r){    quicksortB(a,l,r,0);}

其中, #define digit(A,B) A[B] 表示获得A中对应B位的位数。

2. MSD基数排序

二进制快速排序中,实际上采用的基数R=2。更一般的情况下,每次划分将文件分为R部分,每个部分称为
基数排序最重要的特性就是可以对字符串类型的关键字进行排序。
在下面的具体实现中,最后添加一个循环,用来对同一数字开始的关键字的每个子文件进行递归调用。实现时使用了一个足够大的可以保存输入文件副本的辅助数组aux。

#define bin(A) 1+count[A] //返回A桶元素个数+1void radixMSD(Item a[],int l,int r,int w){    int i,j,count[R+1];    if(w>bytesword) return;//如果要比较的位w超过了bytesword,则结束递归返回    if(r-1<=M)    {insertion(a,l,r);return;}    for(j=0;j<R;j++) count[j]=0;//先将R个桶清空    for(i=l;i<=r;i++)        count[digit(a[i],w)+1]++;//将对应的桶的计数+1    for(j=1;j<R;j++)        count[j]+=count[j-1];    for(i=l;i<=r;i++)        aux[count[digit(a[i],w)]++]=a[i];//按照一次排序顺序把数组复制到aux中    for(i=l;i<=r;i++)        a[i]=aux[i-1];//从辅助数组aux中把排好一遍序的数组再赋给a[]    radixMSD(a,l,bin(0)-1,w+1);    for(j=0;j<R-1;j++)        radixMSD(a,bin(j),bin(j+1)-1,w+1);//对同一个桶中的元素进行递归排序}

3. LSD基数排序

LSD基数排序是从右到左检查字节,当使用的排序方法稳定时,LSD基数排序是高效的。

void radixLSD(Item a[],int l,int r){    int i,j,w,count[R+1];    for(w=bytesword-1;w>=0;w--)    {        for(j=0;j<R;j++)            count[j]=0;//先将R个桶清零        for(i=l;i<=r;j++)            count[digit(a[i],w)+1]++;//对应桶的个数加1        for(j=1;j<R;j++)            count[j]+=count[j-1];//使元素找到实际所在位置        for(i=l;i<=r;i++)            aux[count[digit(a[i],w)]++]=a[i];//按照一次排序顺序把数组复制到aux中        for(i=l;i<=r;i++)            a[i]=aux[i-1];//从辅助数组aux中把排好一遍序的数组再赋给a[]    }}
0 0