王逸松基数排序排序

49 篇文章 1 订阅
30 篇文章 1 订阅

移植了一个别人写的 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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值