【基数排序】基数排序

Algorithm

Task

给定 n 个整数,请排序后输出

Limitations

要求时间复杂度 O((n+T)logTA),空间复杂度 O(T) ,其中 T=32768A 是序列中最大元素的值

Solution

前两天小学妹问我基数排序怎么写,然后我就想起来以前给 ddosvoid 大爷口胡过一个排序,大爷听完说这就是基排,于是就讲给了小学妹(雾),但是我并不确定这是不是基排(((,总之复杂度一致就完事了

考虑桶排序,将所有数字压入桶中,正向扫描整个桶即可。但是当 A 过大时,空间无法承受。

考虑这样一个事实:对于两个数字 A, B,将他们二进制分成两段,先比较前半段,如果大小不同,那么前半段的大小关系即为 A, B 的大小关系,否则比较后半段,二进制后半段较大的一定更大。

我们发现这个结论可以拓展到将数字分成任意段,于是我们考虑将二进制每 log2T 位分一段,对每段做桶排序,然后合并结果即可。

那么出现了一个问题:如果从前向后进行比较的话,需要对前面二进制相同的每组数字分别桶排序,这样最多会做 O(n) 次桶排序,每次 O(T),总复杂度 O(nT),当场去世。

但是考虑一个事实:桶排序是稳定的排序,即如果在某次排序中 A 先于 B 被扫描到,且本次排序认为 A=B,则扫描桶的时候 A 也会先于 B 被扫描。于是我们可以从后往前比较每段,在每次排序前,我们保证已经排过的段的部分的大小关系,在排序结束后,按照新的大小关系从桶中取出。由于之前排过的段的大小已经确定,且桶排序是稳定的,所以这次排序以后已排段的大小关系还是正确的。数学归纳可以证明这样排序的正确性。

考虑复杂度:一共进行了 O(logTA) 次排序,每次 O(n+T) 进行桶排,于是总时间复杂度 O((n+T)logTA);空间上,桶排只需要需要 O(T) 的空间。

事实上,如果数据中有负数,只需要正负分开,分别做一遍即可。

Sample

【P1177】【模板】快速排序

Description

n 个值域为 [1,109] 的整数,要求排序后输出

Limitaions

n105

Solution

板板题

Code

#include <cstdio>
#include <vector>

const int t = 15;
const int d = 32767;
const int maxn = 100005;
const int maxt = 32768;

struct M {
  int pre, pro;
  
  M (const int x = 0) : pre(x >> t), pro(x & d) {}
};
M MU[maxn];

int n;
int ans[maxn];
std::vector<int>bk[maxt];

void Radix_Sort();

int main() {
  freopen("1.in", "r", stdin);
  qr(n);
  for (int i = 1, x; i <= n; ++i) {
    x = 0; qr(x); MU[i] = M(x);
    ans[i] = i;
  }
  Radix_Sort();
  for (int i = 1; i <= n; ++i) {
    qw((MU[ans[i]].pre << t) | MU[ans[i]].pro, i == n ? '\n' : ' ', true);
  }
  return 0;
}

void Radix_Sort() {
  for (int i = 1; i <= n; ++i) {
    bk[MU[ans[i]].pro].push_back(ans[i]);
  }
  int cnt = 0;
  for (auto &i : bk) {
    for (auto u : i) {
      ans[++cnt] = u;
    }
    i.clear();
  }
  for (int i = 1; i <= n; ++i) {
    bk[MU[ans[i]].pre].push_back(ans[i]);
  }
  cnt = 0;
  for (auto &i : bk) {
    for (auto u : i) {
      ans[++cnt] = u;
    }
  }
}
posted @   一扶苏一  阅读(822)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示