基数排序——基数为10

本文详细介绍了基数排序算法的工作原理,包括如何通过键值部分信息将元素分配到桶中进行排序,以及其实现过程中的4个步骤。算法特点是稳定性且时间复杂度为O(nlogm)。作者还提供了C++代码示例,并讨论了该算法在特定情况下的适用性。
摘要由CSDN通过智能技术生成

什么是基数排序?

以下内容来自百度

基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin
sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O
(nlogm),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。

基数排序使用桶每一位分别排序后再组合起来(对于每一位使用桶排)
看个图就懂了
基数排序模拟

我们要先搞懂基数的概念:基数是你排序使用的桶的大小。比如图上用的桶是从 0 − 9 0-9 09 也就是 10 10 10 的大小,我们的基数就是 10 10 10

实现

基数排序共有 4 4 4 步:

  1. 计算每一个数的位数。
  2. 计算出当前排序的那一位的值,这里我们有一个公式:设当前数为 n n n 要求的位数为 k k k (个位为 0 0 0)则有 a n s w e r = ( n ÷ 基 数 k ) % 基数 answer=(n \div 基数^k) \% 基数 answer=(n÷k)%基数
  3. 将处理完的一位数所代表的下标加入桶,本人用的是 v e c t o r vector vector
  4. 将桶中排好序的数据重新加入原数组

第一部代码

for(int j=0;j<n;j++) wsa[j]=ws(a[j]);//ws函数用于计算位数

w s ws ws 函数

int ws(int k){
	int ans=0;
	while(k){
		ans++;
		k/=10;
	}
	return ans;
}

第二部分代码

for(int j=0;j<n;j++){
	w[j]=0;
	if(wsa[j]<i+1) continue;//需要特判这一位是否存在
	w[j]=(a[j]/ten[i])%10;//记录当前位的值; 
}

第三部分代码

for(int j=0;j<n;j++){//vector
	b[w[j]].push_back(j);//加入桶 
	//if(w[j]==0) cout<<j<<endl;//调试
}

第四部分代码

int cnt=0;
for(int j=0;j<10;j++){
	for(int k=0;k<b[j].size();k++){//重新开一个数组,避免覆盖
		c[cnt]=a[b[j][k]];//处理完放回原数组;
		cnt++;
	}
	while(b[j].size()) b[j].pop_back();
}
for(int j=0;j<n;j++) a[j]=c[j];

完整代码

#include<bits/stdc++.h>
using namespace std;
int n,a[10005],mxws=1,c[10005];
int ten[10],w[10005],wsa[10005]; 
vector<int> b[10]; 
int ws(int k){
	int ans=0;
	while(k){
		ans++;
		k/=10;
	}
	return ans;
}
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
		wsa[i]=ws(a[i]);
		if(wsa[i]>mxws) mxws=wsa[i];//求最高位数 
	}
	ten[0]=1;
	for(int i=1;i<10;i++) ten[i]=ten[i-1]*10;//记录10^x 
	for(int i=0;i<mxws;i++){
		for(int j=0;j<n;j++) wsa[j]=ws(a[j]);
		for(int j=0;j<n;j++){
			w[j]=0;
			if(wsa[j]<i+1) continue;
			w[j]=(a[j]/ten[i])%10;//记录当前位的值; 
		}
		for(int j=0;j<n;j++){
			b[w[j]].push_back(j);//加入桶 
		}
		int cnt=0;
		for(int j=0;j<10;j++){
			for(int k=0;k<b[j].size();k++){
				c[cnt]=a[b[j][k]];//处理完放回原数组;
				cnt++;
			}
			while(b[j].size()) b[j].pop_back();
		}
		for(int j=0;j<n;j++) a[j]=c[j];
	}
	for(int i=0;i<n;i++) cout<<a[i]<<" ";
	return 0;
} 

附样例:

5
1 5 3 2 4
5
5 22 10 6 78

总结

基数排序的时间复杂度比较抽象,要看你的基数选的是多少,比如我的代码的复杂度就是 O(10N)
对于用快速排序超时,用桶排序超空间的排序题很有用
最后求关 (^o^)

  • 32
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值