基数排序

基数排序:

在待排序序列中,每个数据在各个数位上可能的取值总数称为基数。如:在十进制中,数据某一位的取值为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 14


void 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};
	int	auxArray[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};  //increase
	int 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");


}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值