第三章:查找与排序(下)----------- 3.21基数排序

基数排序:

       基数排序过程无须比较关键字,而是通过“分配”和“收集”过程来实现排序,它的时间复杂度可达到线性阶:O(n)。(ps:kN)。对于十进制数来说,每一位的数在[0,9]之中,d位的数,则有d列。基数排序首先按低位有效数字进行排,然后逐次向上一位进行排序,直到最高位排序结束

 约定: 待排数字中没有0,没有负数(有负数,做一次转换全部变为正数即可

算法过程: 

(1)、假设有欲排数据序列如下所示:

73 22 93 43 55 14 28 65 39 81。

首先根据个位数的数值,在遍历数据时将它们各自分配到编号0至9的桶(个位数值与桶号一一对应)中。

分配结果(逻辑想象)如下图所示:

分配结束后。接下来将所有桶中所盛数据按照桶号由小到大(桶中由顶至底)依次重新收集串起来,得到如下仍然无序的数据序列:

81 22 73 93 43 14 55 65 28 39

(2)、接着,再进行一次分配,这次根据十位数值来分配(原理同上),分配结果(逻辑想象)如下图所示:

分配结束后。接下来再将所有桶中所盛的数据(原理同上)依次重新收集串接起来,得到如下的数据序列:

14 22 28 39 43 55 65 73 81 93。

(3)以此类推……

如果排序的数据序列有三位数以上的数据,则重复进行以上的动作直至最高位数为止。

代码:

#include<iostream>
#include<cmath>
#include<vector> 
using namespace std;

/**********************************/ 
//函数声明: 
void sort(int arr[],int d,int length);
void putInBucket(int data,int digitOn);
int getDigitOn(int src,int d);
/**********************************/

/***********************************/
//全局变量:
vector<int> bucket[10];


//将数组arr,按d这个位来分配和收集 
void sort(int arr[],int length){
	int d=1;//入桶依据的位初始化为1
	
	int maxn=arr[0];//数组的最大值 
	for(int i=1;i<length;i++){
		maxn=max(maxn,arr[i]);
	} 
	
	int dNum=1; //最大值有多少位
	while(maxn/10!=0){
		dNum++;
		maxn/=10;
	}
		
	while(d<=dNum){
		//依据第二个参数入桶和出桶
		sort(arr,d++,length); 
	} 	
} 

// 重载的sort:将数组arr, 按d这个位来分配和收集
void sort(int arr[],int d,int length){
	//全部入桶
	for(int i=0;i<length;i++){
		putInBucket(arr[i],getDigitOn(arr[i],d));
	} 
	
	//出桶 
	//每个桶中的元素依次压入原数组
	int k=0;
	for(int j=0;j<10;j++){
		while(bucket[j].size()){
			arr[k++]=bucket[j].front();
			bucket[j].erase(bucket[j].begin());  //比较巧妙,移除第一个元素!
		}
	}	
} 
 
//得到十进制数src的第d位:
int getDigitOn(int src,int d){
	return src/(int)(pow(10,d-1))%10;
} 

void putInBucket(int data,int digitOn){  
	switch(digitOn){
		case 0:
			bucket[0].push_back(data);
			break;
		case 1:
			bucket[1].push_back(data);
			break;
		case 2:
			bucket[2].push_back(data);
			break;
		case 3:
			bucket[3].push_back(data);
			break;
		case 4:
			bucket[4].push_back(data);
			break;
		case 5:
			bucket[5].push_back(data);
			break;
		case 6:
			bucket[6].push_back(data);
			break;
		case 7:
			bucket[7].push_back(data);
			break;
		case 8:
			bucket[8].push_back(data);
			break;
		case 9:
			bucket[9].push_back(data);
			break;	
	}
		
}

int main(){
    
    int arr[]={18,13,17,26,29,38,31,69,51};
	int len=9;
	
	sort(arr,len);
    
    //打印结果:
	for(int i=0;i<len;i++){
		cout<<arr[i]<<" ";
	} 
    
	return 0;	
}

 得到十进制数src的第d位(需背住):

 //得到十进制数src的第d位:
int getDigitOn(int src,int d){
	return src/(int)(pow(10,d-1))%10;
} 

运行结果:

小结:

计数排序: 适用于小范围数据;

桶排序:    适用于均匀分配的数据。

 

参考:lanqiao.coding.me

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值