基数排序

桶排序:

将数字放在数组对应下标的位置,这样一次遍历即可按照顺序输出所有的元素

但是如果数字范围很大,并且分布非常不均匀的话,这样会造成严重的浪费,并且数组的容量有限这样也可能存不开,根据这些不足,我们将其进行改进,形成基数排序

 

基数排序:

算法实现步骤:

按照个位数进行一次排序,按照十位数进行一次排序,.....重复m次(m为这些数字中最多的位数,(b为进制))。

 

例:对110,119,7,911,114,120,122进行排序

 m 为3

 

第一趟分配 

                                                              

第一趟收集:

110, 1209111221147119

 

第二趟分配:

                                              

第二趟收集:

111, 1149111191201227 

第三趟分配: 

                                           

                                      

第三趟收集:

7, 111114119120122911

大功告成!!!

基数排序实在是太神奇了:

    空间复杂度不大,时间复杂度是常数阶的,并且还稳定!!!,

但是有些特殊情况还是需要处理一下,比如如果有负数怎么办,我采用的是两次排序的方法,负数特殊处理一下


有负数的情况,用vector实现的基数排序Code:

/*
以十进制为底的基数排序
正负数都可以用
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<cmath>
#include<cstdlib>
using namespace std;
const int maxn = 100010;
int num1[maxn];
int num2[maxn];
typedef queue<int> Queue;
vector<Queue> V1;
vector<Queue> V2;

void init()
{
    for(int i = 0; i <= 9; i++)
    {
        queue<int> Q;
        V1.push_back(Q);
        V2.push_back(Q);
    }
    return ;
}

int main()
{
    int n;
    init();
    scanf("%d", &n);
    int maxx1 = 0;   //正数排序
    int maxx2 = 0;   //负数排序
    int n1 = 0, n2 = 0;
    for(int i = 0; i < n; i++)
    {
        int x;
        scanf("%d", &x);
        if(x >= 0)
        {
            num1[n1++] = x;
            int xx = (int)log10((double)x) + 1;
            maxx1 = max(xx, maxx1);
        }
        else
        {
            x = abs(x);
            num2[n2++] = x;
            int xx = (int)log10((double)x) + 1;
            maxx2 = max(xx, maxx2);
        }
    }
    // 对负数
    for(int i = 0; i < maxx2; i++)
    {
        for(int j = 0; j < n2; j++)
        {
            int x = (num2[j]/((int)pow(10, i))) % 10;
            V2[x].push(num2[j]);
        }
        int ans = 0;
        for(int k = 0; k <= 9; k++)
        {
            while(!V2[k].empty())
                num2[ans++] = V2[k].front(), V2[k].pop();
        }
    }
    //对正数
    for(int i = 0; i < maxx1; i++)
    {
        for(int j = 0; j < n1; j++)
        {
            int x = (num1[j]/((int)pow(10, i))) % 10;
            V1[x].push(num1[j]);
        }
        int ans = 0;
        for(int k = 0; k <= 9; k++)
        {
            while(!V1[k].empty())
                num1[ans++] = V1[k].front(), V1[k].pop();
        }
    }
    for(int i = n2-1; i >= 0; i--)
        if(i == n2-1) cout << -1* num2[i];
        else          cout << " " << -1*num2[i];
    for(int i = 0; i < n1; i++)
        if(n2 == 0 && i == 0) cout << num1[i];
        else                  cout << " " << num1[i];
    return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值