移植了一个别人写的 B a s e 256 Base_{256} Base256 基数排序的代码, 效率远赶不上原版的效率,在洛谷上排序 1 0 5 10^5 105 个数不开 O 2 O_2 O2 优化平均用时 12 m s 12ms 12ms。
/// GGN_2015 2021-06-07 试图移植一个 王逸松基数排序
#pragma GCC diagnostic error "-ansi -traditional-cpp -std=c++11 -Ofast -Wall -Wextra -pedantic -pg -g3"
#include <stdio.h>
#include <string.h>
static char Buffer[100000],*PointerI = Buffer,*PointerII = Buffer; /// 快速读入缓冲区
/// PointI 指向缓冲区首部, PointerII 指向缓冲区尾部
#ifdef ONLINE_JUDGE /// 在 OJ 上采用缓冲区读入优化
#define GetCharQuick() \
(\
PointerI == PointerII /*相等时表示缓冲区为空*/ \
&& /*利用短路性:如果缓冲区为空则读入一组值存入 Buffer*/ \
( \
PointerII = (PointerI = Buffer) + \
fread(Buffer, sizeof(char), 100000, stdin), /*重新读入缓冲区内容*/ \
/*并将PointerI 定位到缓冲区首部, PointerII 定位到缓冲区尾部*/ \
PointerI == PointerII /*如果 相等说明文件中没有剩余字符*/\
) \
? EOF /*如果文件中没有剩余字符返回 EOF*/ \
: *(PointerI ++) /*否则返回当前缓冲区中的第一个字符并将首部指针向后移动一个字节*/ \
)
#else
#define GetCharQuick() (getchar())
#endif
inline int ReadInt() /// 从文件读入一个整数
{
register int x = 0;
register char a = GetCharQuick();
while(a < '0'|| a > '9') a = GetCharQuick(); /// 跳过所有非数字字符
while(a >='0'&& a <='9') {
x = (x<<1) + (x<<3) + (a^48); /// 把 a 追加到 x 的个位上
a = GetCharQuick();
}
return x;
}
char OutputBuffer[10000000] , *OutputPointer = OutputBuffer; /// 输出缓冲区
/// OutputPointer 是输出缓冲区的指针
inline void WriteInt(int x) /// 输出一个整数到输出缓冲区
{
static short Stack[35];
register int StackTop = 0; /// 记录一个数值栈
if(!x) Stack[++ StackTop] = 0; /// 特判输出零的情况
while(x) {
Stack[++ StackTop] = x % 10;
x /= 10;
}
while(StackTop) {
*(OutputPointer ++) = Stack[StackTop --] ^ '0';
}
}
#define BaseN 256 /// 以 256 为基进行基数排序
int cnt0[BaseN], cnt1[BaseN], cnt2[BaseN], cnt3[BaseN]; /// 分别记录每一相邻八位的01串的出现次数
int A[100005], B[100005];
int main() {
int n = ReadInt();
register int i, *t = A + n;
for (; t != A;) { /// t 从后向前枚举 a 数组中的所有位置, 下标从 n-1 到 0
*--t = ReadInt();
++ cnt0[*t &255],
++ cnt1[(*t>>8) &255],
++ cnt2[(*t>>16)&255],
++ cnt3[(*t>>24)];
}
for (i = 1; i <= 255; ++ i) { /// 求前缀和
cnt0[i] += cnt0[i-1];
cnt1[i] += cnt1[i-1];
cnt2[i] += cnt2[i-1];
cnt3[i] += cnt3[i-1];
}
for (i = n - 1; ~i; -- i) B[-- cnt0[ A[i] &255]] = A[i]; /// 将 A 中数值按照 cnt0 排序后存入 B
for (i = n - 1; ~i; -- i) A[-- cnt1[(B[i]>>8) &255]] = B[i]; /// 将 B 中数值按照 cnt1 排序后存入 A
for (i = n - 1; ~i; -- i) B[-- cnt2[(A[i]>>16)&255]] = A[i]; /// 将 A 中数值按照 cnt2 排序后存入 B
for (i = n - 1; ~i; -- i) A[-- cnt3[(B[i]>>24)] ] = B[i]; /// 将 B 中数值按照 cnt3 排序后存入 A
t = A;
register int *Ending = A + n;
for (; t != Ending; ++ t) { /// 从前到后枚举 A[0] 到 A[n - 1]
WriteInt(* t);
*OutputPointer ++ = ' '; /// 向输出缓冲区中输入一个空格
}
fwrite(OutputBuffer , sizeof(char), OutputPointer - OutputBuffer, stdout); /// 将输出缓冲区中的内容输出到 stdout
return 0;
}