基数排序

来源:互联网 发布:mac 查看安装路径 编辑:程序博客网 时间:2024/06/04 00:43

基数排序:

在待排序序列中,每个数据在各个数位上可能的取值总数称为基数。如:在十进制中,数据某一位的取值为0~9,那么基数就是10.

在八进制排序中,基数就是8.

基数排序方法有两种:一种是最高位优先(MSD),另一种是最低位优先(LSD)。

以MSD为例:

基数排序需要以下步骤:

生成count数组、将待排序元素放入对应的桶中、将排好序的桶中的元素再复制到原数组中的对应位置、递归(d由最高位转换到次高位)

(1)count[k]数组:

i位取值为k的元素有count[k]个。

当基数为10时,k0~9.

待排序元素:[left,right]

生成count数组,要取数据任一位的值,为此,设计一个位取数器:

位取数器:

input:数据 位数

output:该位的取值

int getdigit(int num,int dt)  //位取数器,num,适用范围:0~999
{

int g;
if(dt==3)
{
if(num>=0&&num<=9)
  return 0;
else if(num>=10&&num<=99)
           return 0;
else 
        return num/100;


}
if(dt==2)
{
if(num>=0&&num<=9)
  return 0;
else if(num>=10&&num<=99)
           return num/10;
else 
{
g=num/100;
return (num-g*100)/10;

}


}
if(dt==1)
{
if(num>=0&&num<=9)
  return num;
else if(num>=10&&num<=99)
{
g=num/10;
  return num-g*10;
}

else 
{
g=num/10;
return num-g*10;

}


}
  return 0;
}

(2)用辅助数组auxArray[len]来模拟桶,每个桶的大小由count[k]来确定。

要确定每个桶在auxArray[len]中的位置:

假设有count[k]数组:



count[k]中可以看出共有12个待排序元素,分布在0~910个桶中。

每个桶的位置在auxArray[12]中如下:

(48号桶不存在,即没有这样的待排序元素)


即:第k号桶的首个位置是:auxArray[count[0]+count[1]+…+count[k-1]]

k号桶的下一个位置是:

auxArray[count[0]+count[1]+…+count[k-1]+1+…]

现在开始将待排序的元素放到对应的桶中:

桶分两种情况:

1、  能装1个元素

2、  能装多个元素

为此,要对每一个桶设置一个计数器。在桶中每放入一个元素,这个桶的计数器就加1。在桶中放入元素前,先检测计数器,用计数器来确定要放入的位置。

计数器设置:

cnt[10]

初始化:int cnt[10]=0;

for(i=left;i<=right;i++)//扫描待排序元素

{  firstPos=0;//桶的首位置归零

bucket=a[i]/x;  //确定哪个桶

for(j=0;j<=bucket-1;j++)  //确定桶的首位置

{

   firstPos=firstPos+count[j];

}


auxArray[firstPos+cnt[bucket]]=a[i];

    cnt[bucket]++; //记录这个桶的下一个位置

 

}

(3)将排好序的桶中的元素再复制到原数组中的对应位置:

要考虑auxArray[]a[]的对应关系:

若原数组为:a[left,right]

再假设:count[2]=1 count[3]=2  count[4]=1

那么:auxArray[]:


可以看出auxArray的大小与count[k]有关。

auxArray[count[0]+count[1]+…+count[9]]

而且:auxArray[0]对应a[left],auxArray[1]对应a[left+1]…

for(i=0;i<count[0]+…+count[9];i++)

   a[left+i]=auxArray[i];

(4)递归:

由最高位转换到次高位;

递归结束的条件:if(d>0)

要确定递归的桶(即存在多个元素的桶)和这些桶的边界。

a[left,right]对应了0~9号桶。

例如:

count[]:


a[](原数组):



需要递归的桶为:1257

它们的起始下标(st)表示:

1:left+(count[0])

2:left+(count[0]+count[1])

5:left+(count[0]+count[1]+…+count[4])

7:left+(count[0]+…+count[6])

它们的终止下标表示:

1:st+count[1]-1

2:st+count[2]-1

5:st+count[5]-1

7:st+count[7]-1


for(i=0;i<10;i++)

{  s=0;st=0;ed=0;//归零

  if(count[i]>1)//需要递归的桶

{

   for(j=0;j<i;j++)

s=s+count[j];

}

   st=left+s;         //i个桶的起始下标

   ed=st+count[i]-1; //i个桶的终止下标

}

radixsort(a,st,ed,d-1);

 }


总结:一定要注意变量的适用范围(是否需要在下一次循环开始前置零)  声明的变量和数组要初始化

附程序:

// node.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <string.h>#include <stdlib.h>#define len 14void radixsort(int t[],int left,int right,int d);int getdigit(int num,int dt);int getdigit(int num,int dt)  //位取数器{int g;if(dt==3){if(num>=0&&num<=9)   return 0;else if(num>=10&&num<=99)           return 0;else         return num/100;}if(dt==2){if(num>=0&&num<=9)   return 0;else if(num>=10&&num<=99)           return num/10;else {g=num/100;return (num-g*100)/10;}}if(dt==1){if(num>=0&&num<=9)   return num;else if(num>=10&&num<=99){g=num/10;  return num-g*10;}else {g=num/10;return num-g*10;}}  return 0;}void radixsort(int t[],int left,int right,int d){  if(d>0) //递归结束的条件 {//产生count数组   int m,n,sum,w;   int count[10]={0};   for(m=left;m<=right;m++)   {   w=getdigit(t[m],d);   count[w]++;   }   sum=0;    for(n=0;n<10;n++)sum=sum+count[n];//将待排序元素放入对应的桶中    int cnt[10]={0};intauxArray[len]={0};int bucket,firstPos,i,j;    for(i=left;i<=right;i++){firstPos=0;bucket=getdigit(t[i],d);for(j=0;j<=bucket-1;j++){   firstPos=firstPos+count[j];}    auxArray[firstPos+cnt[bucket]]=t[i];    cnt[bucket]++;}//将桶中的元素返回给原数组    int k; for(k=0;k<sum;k++)     t[left+k]=auxArray[k];/*int tt;for(tt=0;tt<len;tt++){printf("%d",t[tt]);printf("\t");}printf("\n");*///递归int a,b,s,st,ed;for(a=0;a<10;a++){s=0;st=0;ed=0;if(count[a]>1){for(b=0;b<a;b++)s=s+count[b];            st=left+s;    ed=st+count[a]-1;}radixsort(t,st,ed,d-1);}}//if}void main(int argc, char* argv[]){int b[len]={361,9,667,26,587,3,666,103,500,79,325,46,518,45};  //increaseint r;    int ttt;for(ttt=0;ttt<len;ttt++){printf("%d",b[ttt]);printf("\t");}printf("\n");radixsort(b,0,len-1,3);    printf("\n");for(r=0;r<len;r++){printf("%d",b[r]);printf("\t");}   printf("\n");}