编程珠玑(一)位图

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

这个问题是编程之美中第一章开篇提到的问题,bitmap排序。大概意思是这样的,要对n个不重复的整数进行排序,每个数小于n(10的7次方)要求内存1M。其实是区号为800开始的电话号码,800不算在内。这个是典型的位图(bitmap,应该是位映射我觉得,估计是好翻译才把map翻译成图的)。下面是代码:

#include <iostream>
using namespace std;

const int NUM_COUNT = 10000000;
const int MAXLINE = 9; //缓冲区大小,最大读到的为8位整数
const int MASK = 0x1F; //后5位表示在一个int型中的对应的位
const int SHIFT = 5;

inline void setBit(int *a, int num);
inline int getBit(int *a, int num);

int main()
{
        int a[NUM_COUNT/32 + 1] = {0};
        FILE *fp;
        char buf[MAXLINE];
        fp = fopen("./num.txt", "r");
        if(fp)
        {
                while(fgets(buf, MAXLINE, fp) != NULL)
                {
                        int num = atoi(buf);
                        setBit(a, num);
                }
        }

        for(int i=0; i<NUM_COUNT; i++)
        {
                if(getBit(a, i))
                        printf("%d\n", i);
        }
        return 0;
}

inline void setBit(int *a, int num)
{
        a[num>>SHIFT] |= (1<<(num & MASK));
}

inline int getBit(int *a, int num)
{
        return a[num>>SHIFT] & (1<<(num & MASK));
}



编程珠玑后面还有几个习题供思考,简单写下

(1)程序要求有1M空间,但是我们的代码要使用1.25M的空间,如果1MB空间是严格的边界,如何处理?
1M内存空间共有位为1*1024*1024*8=838W,还差170w个位。可以按照数的特征去掉一部分数,例如没有以0和1开头的电话,这样就去掉200w个,就可以满足了(这个是习题解答上给的,没有以1开头的电话么)。还可以用两趟排序来解决。

(2)如果不是每个整数最多出现一次,而是每个整数最多出现10次,如何改进?
这个用四位即可表示0~15,所以用四位表示一个整数即可(可以是每个整数最多出现15次)。代码如下:

#include <iostream>
using namespace std;

const int NUM_COUNT = 10000000;
const int MAXLINE = 9; //缓冲区大小,最大读到的为8位整数
const int MASK = 7; //后3位表示在一个int型中的对应的位
const int SHIFT = 3; //4比特表示一个数,一个32位的整数能保存8个数

inline void addBit(int *a, int num);
inline int getBit(int *a, int num);

int main()
{
        int a[NUM_COUNT/8 + 1] = {0};
        FILE *fp;
        char buf[MAXLINE];
        fp = fopen("./num.txt", "r");
        if(fp)
        {
                while(fgets(buf, MAXLINE, fp) != NULL)
                {
                        int num = atoi(buf);
                        addBit(a, num);
                }
        }

        for(int i=0; i<NUM_COUNT; i++)
        {
                if(int count = getBit(a, i))
                        while(count > 0)
                        {
                                printf("%d\n", i);
                                count--;
                        }
        }
        return 0;
}

inline void addBit(int *a, int num)
{
        //先取出来num对应的四位的值value
        int value_mask = 15<<((num & MASK) * 4);
        int value = a[num>>SHIFT] & value_mask;
        value >>= ((num & MASK) * 4);
        //数目加一,表示多出现一次
        value++;
        //重新设置原来的的4位值
        value <<= ((num & MASK) * 4);
        a[num>>SHIFT] &= ~value_mask;
        a[num>>SHIFT] |= value;
}

inline int getBit(int *a, int num)
{
        int value_mask = 15<<((num & MASK) * 4);
        int value = a[num>>SHIFT] & value_mask;
        value >>= ((num & MASK) * 4);
        return value;
}


 

(3)以前免费电话的区号都是800,现在又有区号为877、888等电话,又该如何按照电话号码排序呢?
两种思路:
1)给每个区号赋予一个权值(为素数),例如800为2,877为3,888为5,用乘积来表示不同区号相同号码出现的情况,例如只出现800的某个电话,则为2,出现800和877的同一个号码,则为6,同理都出现为30。情况一共有八种,一个都没出现、只有一个出现、只有一个没出现、都出现这八种情况,可以用三位来表示,如果对内存有要求,用三位来表示这八种情况即可。这里只是一种思路。当区号较多的时候,素数难找,而且占用空间较大
2)还是位图,每个号码用三位表示即可,每一位对应一个区号。如果内存有要求,从前往后多次排序。

编程珠玑 这不是本具体算法的讲解或者代码编写的教程,但是从书中的字里行间,我们可以学到的是更多的软知识:对编程新的认识、更加发散的思维方式、更严格的代码要求、堪比瑞士军刀的小技巧…… 编程也许入门并不难,但是要想真正成为名优秀的软件工程师,还是需要很多锤炼。内外兼修,方成大器。 基础篇 第章 开篇首先作者提出个实际问题: 如何给磁盘的某个文件排序,更具体来说就是是对个最多包含1千万条记录,每条 阅读详情

相关推荐

编程珠玑(好书,看了以后让你茅舍顿开)

好书,看了以后让你茅舍顿开,很多公司面试都会用到这里面的题。。。。。。

编程素人眼里的编程珠玑

@编程珠玑-吐槽向 编程素人眼里的编程珠玑 作为个cs专业的素人, 在每个立志学好计算机的深夜搜索如何做名优秀的程序员时,都会被推荐这本书,终于我下单了,并且在个阳光并不充足的周末,我看完了这本书。 第章 我个人认为第章是我在这本书里最大的收获。第章大概讲述了分析问题的重要性。在实际应用情境中,当我们遇见即使个很常见的问题,我们仍然需要分析在我们的情境中,我们的数据的特点,然后根据数据的特点选择个最适合的算法,而不是个理论上的最好的算法。 第二章 二分法, 向量旋转方法以及变词问题。

baozi_sun的博客 244

编程珠玑,适合各编程语言提升编程思想

免费放送。提升编程技术和思想的宝典,也是各大名企面试的应答宝典,不看就错过了提升自己的机会。

编程珠玑》:本让我着迷的计算机书籍

我认为这本书是本计算机书籍的宝藏,它不仅适合初学者,也适合高手,它不仅适合学习,也适合娱乐,它不仅适合阅读,也适合反复品味。作者通过个简单的例子,演示了如何从个 O(n2)算法,逐步改进到个 O(n)算法,最后达到个 O(1)算法。这本书是他在《通信》杂志上发表的系列专栏的合集,每篇专栏都是个独立的主题,涉及到算法、数据结构、性能优化、调试、测试等方面的编程技巧和案例。作为名计算机爱好者,我经常阅读些计算机书籍,来提高我的编程技能和扩展我的视野。

fasdfasfwerwqf的博客 326

阅读者(十七):编程珠玑,字字珠玑

无论你自称是“程序猿”还是“攻城师”,只要在写程序,都免不了要和算法打交道。说起算法,第本从你的记忆中检索出的图书是什么呢?是经典的大部头《算法导论》?还是之前大红大紫的《编程之美》?以前它们几乎是同时映入我脑海的,分不清谁先谁后,这两本书我都读过,前者是在学校的算法课上,而后者则是在毕业求职前。\最近,我终于有了个明确的答案,在这些算法相关的书籍中,最让我爱不释手的是《编程珠玑》这本薄薄的小...

cpongo5 189

推荐计算机算法好书——编程珠玑

<br />简介   · · · · · ·   本书是计算机科学方面的经典名著《编程珠玑》的姊妹篇,讲述了对于程序员有共性的知识。书中涵盖了程序员操纵程序的技术、程序员取舍的技巧、输入和输出设计以及算法示例,这些内容结合成个有机的整体,如串串珠玑展示给程序员。本书适合各级程序员阅读参考。...<br />  【媒体评论】<br />  “《编程珠玑》第1版是对我职业生涯早期影响最大的书之,其中的许多真知灼见多年之后仍然使我受益匪浅。Jon在第2版中对素材进行了大量更新,许多新内容让我耳目新。”.<

dawnchow08的专栏 762

计算机基础知识大全_计算机专业必读哪些经典书籍?

疫情之下的今年,小编也不知道程序员的求职之路是否顺畅,开学季也不清楚是哪个月份,如果还没有毕业的计算机专业的你,需要看下这份书单,为将来走出校门做准备,虽然这样的书单很多人推荐过,小编还是想亲自来份。当然,程序员也非常适用此书单。IT人文篇1、编程珠玑 第2版[美] 乔恩·本特利(Jon Bentley) 著,黄倩,钱丽艳 译《编程珠玑》第版是我早期职业生涯中阅读过的对我影响较大的书籍之,...

weixin_39989941的博客 1672

编程珠玑()位图排序

位图排序本博客为原创博客,转载请标明出处.位图排序的三个阶段 将所有的都置为0,从而将集合初始化为空。 读入非负整数数据,将每个整数对应的都置为1。 检验每,如果是1就输出对应的整数。 C++代码实现//首先是操作函数的简单定义与实现 #define BitsPerWord 32 #define SHIFT 5 #define MASK 0x1F #define N 1000000

渐渐遗忘的记忆 424

位图排序——《编程珠玑》笔记

感叹《编程珠玑》这本书字字珠玑,非常强大,看了有段时间了,所以也行整理下看的过程中的收获和问题。      在开篇第章中,坐着就提出了应用非常广泛、非常强大,适合于海量互异数据排序的算法——位图排序。     问题定义: 对之多只包含n(10^7)个正整数的文件排序,每个数大小都小于n,不允许有重复的数出现,任何个数都至多出现次。     限制:可用的内存空间是有限的(

WuChangsong的博客 791

编程珠玑》阅读小记(1)— 开篇

1. 前言久闻《编程珠玑书的大名,直没有找到合适的机会深入学习阅读,最近终于得以入手,便决心投入细细的研究,提升下自己的编程思想与技术。阅读之后才发现,这本书确实本不可多得的好书。它以计算机领域应用与编程算法相结合,让读者面对实际问题时,不单单局限于考虑该问题的解决方案,而是在入手实践之前能够驻足于考虑,该方案是否符合当前的实际环境,它的时间与空间的消耗是否达到了个比较好的指标。 通过

指尖飞舞 1600

编程珠玑》第章Java代码实现

[size=large]我看算法的时候只看伪代码的话,感觉太抽象,总记不住,我希望能看到真正实现的代码,这样心里会感觉踏实点。 因此,总希望能把书上的算法给具体实现了,这样来能记住算法,加深印象,而来二来也能提高自己的编程水平。 《编程珠玑》的代码已经有C/C++的实现版本了,我在附件也贴出来了,但是,作为个C++语言的入门者,因为还涉及到不知道如何链接C++的函数库等种种问...

limitforest1的博客 437

位图排序

哈哈,第篇博客,意义非凡哈。 将《编程珠玑》第章的位图排序简单的实现了下。 #include #define SHIFT(a) (0x01 #define SHIFTTORIGHT(a) (0x80>>(a)) #define MAX 10      //待排序序列中最大值不大于8*MAX typedef unsigned char uchar;

zephyr_john的博客 155

IT人士必看书籍-编程珠玑(中文)

IT人士必看书籍,免费分享,欢迎大家下载~

编程珠玑》读书笔记(

编程珠玑》(第二版)第部分主要是讲基础 第章 开篇: 本章主要解决的问题是“在内存不足的情况下,如何对数据进行排序”,提出了两种解决方法:归并排序和位图排序。 归并排序:     思想是每次将两个有序表合成个长的有序表,程序般用递归来实现,时间复杂度是O(nlogn),需要O(n)的空间复杂度,稳定。 位图排序

qianqiang1989的专栏 191

位图数据结构的操作

摘自《编程珠玑书第1章习题: 1: #define BITSPERWORD 32 2: #define SHIFT 5 3: #define MASK 0x1F 4: #define N 10000000 5: int a[1 + N/BITSPERWORD]; 6: ...

weixin_30670925的博客 80

编程珠玑》摘要

对《编程珠玑》这本书的些摘要

DaDianJiShiQi的博客 1269

位图法;海量数据处理之位图技巧;位图技巧;海量数据;编程珠玑第二章问题A;40亿整数;腾讯面试题

编程珠玑第二章开始提出了三个问题,其中第个问题是这样的:个顺序文件至多包括40亿个32的整数,这些数是无序的,找出个不在该文件中的32整数。(可能有数字是不在该文件中的,因为2^32总共包括了42+亿个数,因此肯定有整数是不在该文件中的,这是鸽巢原理吧?) 据说这是腾讯的道面试题,大概描述如下: 问题描述: 问题的描述大概就是这样了。 刚看到这个题目就想到了bitmap,很适合使用,下面简单说明下。 1、bitmap方法 如果问题对于内存没有要求,可以采用bitmap的方

疯狂算法~ 6938

位图排序——编程珠玑

位图排序是种效率极高(复杂度可达O(n))并且很节省空间的种排序方法,但是这种排序方法对输入的数据是有比较严格的要求(数据不能重复,大致知道数据的范围)位图排序即利用位图或者向量来表示集合。举个例子,假如有个集合{3,5,7,8,2,1},我们可以用个8的二进制向量set[1-8]来表示该集合,如果数据存在,则将set相对应的二进制置1,否则置0.根据给出的集合得到的set为{1,

晴天的专栏 779

编程珠玑》之位图技术

编程珠玑,相当不错的本书。其中很多金句需要在工作的过程当中,铭记于心: chapter 1,书中的金典语句: @1,明确问题(问对正确的问题),这场战役就成功了90%. @2,几分钟的仔细研究可以大幅削减代码的长度、程序员的时间和程序系统运行的时间。 @3,设计者确定其设计已经达到了完美的标准,不是不能再增加任何东西,而是不能再减少任何东西。 @4,程序员的主要问题,与其说是技术问题,...

sf_jiang的博客 685
上一篇: TCP/IP学习(四)TCP缓冲区大小及限制
下一篇: 编程珠玑(二)字符串左旋
ysu108
博客等级 码龄16年 246粉丝 206原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值