《编程珠玑》备忘录(开篇)---位图排序扩展

在开篇的习题部分,作者提出了一个延伸问题,即当每个整数最多出现10次的时候,这个排序问题应该如何解决。

尽管这次作者大方地没有限制我们可以使用的内存,但是在设计该程序时还应依照勤俭持家的原则:一个硬币掰开用。由于一个整数最多出现10次,那么我需要4位(bits)来对每个整数出现的频数进行统计。按照一般的设定,一个字符(char)往往包含了8个位,联想到作者之前使用位逻辑运算实现位向量的方法,我在这里照葫芦画瓢,使用一个字符的前后4位分别用于统计两个相邻整数出现的次数。

为了表示起来比较方便,我这里使用CHAR_BIT表示一个字符所包含的位数,如果输入文件包含MAXIMUM个整数,我需要建立的数组大小为((MAXIMUM*4-1)/CHAR_BIT)+1,这个设定方法是我从五岳的博客看来的,这样当MAXIMUM*4非0也非CHAR_BIT的倍数时,最多是有一个char不完全利用,但是不会造成浪费。
#define INTBITS 4
#define MAXMUM 10
#define BITS (MAXMUM*INTBITS-1)/CHAR_BIT+1   

char arr[BITS];


给定一个整数k,用右移运算k>>1可以决定k在数组中的下标;接下来我需要保留这个整数的二进制末位来判断k的频数应当在char的哪一部分,如果末位为0,则将其记在char的0-3位;如果末位为1,则将其记录在char的4-7位。
#define SHIFT 1     //log_2(CHAR_BIT/INTBITS) = 1
#define MASK 0x1    //截取最后一位

void incBit(char *bit, int i)
{
    bit[ i>>SHIFT ] += 1<< ((i&MASK)*INTBITS );
}

同理,当提取统计结果时,可以使用同样的方法得到整数k的出现次数,但是上面不同的是,如果对应的位在4-7位,我就需要对其右移4位来得到最终的答案。最后和0xf进行&运算,可以保证最后得到的就是最后4位。
#define MASK2 0xf  //保留所得结果的最后4位

int compareBit(char *bit, int i)
{
    return (bit[ i>>SHIFT ] >> ((i&MASK)*INTBITS) & MASK2);
}

如果MAXMUM的值设为1千万,那么这个程序所占的内存为4M多,我觉得是可以接受的。作者在答案中也提到依然可以使用多趟算法来减少内存占用,只不过时间要多牺牲一些了。
接下来是我测试时用的程序:
#include <iostream>

#define INTBITS 4
#define SHIFT 1
#define MASK 0x1
#define MASK2 0xf
#define MAXMUM 10
#define BITS (MAXMUM*INTBITS-1)/CHAR_BIT+1

using namespace std;

//用于统计整数i出现的频数
void incBit(char *bit, int i)
{
    bit[ i>>SHIFT ] += 1<<( ( i & MASK ) * INTBITS );
}

//用于提取统计结果
int compareBit(char *bit, int i)
{
    return ( bit[ i>>SHIFT ] >> ( ( i&MASK ) * INTBITS ) & MASK2 );
}

int main()
{
    char arr[BITS];
    int test[8] = { 8, 1, 4, 5, 8, 5, 7, 4};

    for(int i=0; i<BITS; i++){
        arr[i] = 0;
    }

    for(int i=0; i<8; i++){
        incBit(arr, test[i]);
    }

    for(int i=0; i<MAXMUM; i++){
        int countNum = compareBit(arr, i);
        if(countNum>0){
            cout<<i<<"; "<<countNum<<endl;
        }
    }

    return 0;
}

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值