编程珠玑 第一章解析

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

问题:

输入:一个最多包含n个正整数的文件,每个数都小于n(n=1000W)。如果在输入文件中有任何整数重复出现就是致命错误。没有其他数据与该整数相关联。

输出:按升序排列的输入整数的列表。

约束:最多有(大约)1 MB的内存空间可用,有充足的磁盘存储空间可用。运行时间最多几分钟,运行时间为10秒就不需要进一步优化了。

方法一:归并排序。(耗时间)

        归并排序需把数据全部读入内存,1000w个整数的大小是1000w*4/(1024*1024)大约是40M(假设一个整数是4字节),显然不能将全部数据读入内存。

方法二:分段排序。(耗时间)

       将这些整数分成40组,分别是[0-249999]  [250000-4999999]  … [9750000-9999999],然后遍历40次。这样时间复杂度是40n,空间复杂度是n/40,比归并要好点。当然也可以把范围扩大或者缩小。

方法三:位图法。

       用1位来表示[0~n-1]中的整数是否存在。1表示存在,0表示不存在。这样的话进行一次遍历,就可以进行排序了,而且空间复杂度是n/(8*1024*1024)。例如对于20个数来说,如果集合是{1,2,3,5,8,13}.那么其位图表示法如下:01110100100001000000(说明:左边第一位表示 0 )。

程序:

利用bitset

#include <iostream>
#include <bitset>
#include <fstream>
using namespace std;
int main()
{
    // 查看bitset的实现可知bitset是利用对unsigned long进行位运算间接实现对位的存储的
    // 如是保存一个32位的bitset实质是保存了4个unsigned long长整数
    bitset<1000000> b;
    b.reset();   
    ifstream in("before_sort.txt");
    ofstream out("after_sort.txt");
    int i;
    while (!in.eof()) {
     in>>i;
     b.set(i);
    }
    for (i=0;i<1000000;++i) {
     if (b[i]==1) {
      out<<i<<endl;
      
    }
    return 0;
}

利用位逻辑运算

事实上,我们是用每一个元素表示一个32位的二进制字符串这样这个元素可以保留相邻32个号码是否存在的信息,数组范围就下降到了10000000/32了,例如对于号码89256,由于89256 mod 32=2789…8,这样我们应该             置a[2789]32位字符串的第8(从低位数起)1现在问题的关键是,如何用位逻辑运算来表示这种操作。

#include <stdio.h>
#include <stdlib.h>

#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1 + N/32];

// 置位函数----用“|”操作符,I & MASK相当于mod操作

//m mod n 运算,当n = 2 的X次幂的时候,m mod n = m & (n-1)
void set(int i) {        a[i>>SHIFT] |=  (1<<(i & MASK)); }
void clr(int i) {        a[i>>SHIFT] &= ~(1<<(i & MASK)); }
int  test(int i){ return  a[i>>SHIFT] & (1<<(i & MASK)); }
int main()
{       int i = 0;
        while (scanf("%d", &i))
   set(i);
        for (i = 0; i < N; i++)
                if (test(i))
     printf("%d\n", i);
        return 0;
}

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

相关推荐

编程珠玑》第二版:中英版书籍与源码实践

编程珠玑》第二版是计算机科学领域中不可多得的经典书籍之一,它以浅显易懂的语言深入浅出地探讨了编程实践中常见而重要的话题。该书不仅覆盖了编程语言、数据结构、算法设计等基础知识,也着重于问题解决的思维方法和最佳实践。我们将会逐章梳理书籍的精粹,介绍每章的核心议题,以及它们对编程领域的长远影响和意义。通过对这些内容的深入分析,读者将能够领略《编程珠玑》在启迪思考和指导实践方面的独特价值。最后,通过案例分析,可以将理论与实践相结合的过程进行可视化。

weixin_32661831的博客 906

编程珠玑详解

编程珠玑

编程珠玑中文版第二版:源码深入解析

标准输入是大多数编程语言提供的基础输入方法,如C/C++中的scanf或Python中的input函数。自定义输入则是针对特定应用需求设计的输入方式,如图形用户界面(GUI)的事件驱动输入或网络通信中的套接字输入。自定义输入通常需要更详细的设计,包括输入数据的格式化、验证和缓冲管理。

weixin_42103128的博客 559

编程珠玑第一章

下午看完编程珠玑第一章,感觉很不错!如作者所说:阅读本书一个提示,不要太快, 一次阅读一章。集中精力思考,解答课后习题。 写总结就是在刚弄懂的时候,这时候是最恰当的时候,最容易接受。 题目要求:一个最多含有1000万个整数的文件,整数没有重复,请输出升序排列。 (约束):最多1M内存,时间10S。 题目很简单,但是分析的过程很经典。 刚开始想法,排序呗。。可是时间要求10S,内

814

编程珠玑第一章:开篇

习题 1. 如果不缺内存,如何使用一个具有库的语言来实现一种排序算法以表示和排序集合?

Code for Yun 1381

编程珠玑第一章 开篇

一,题目:        如何在1MB的空间里面对一千万个整数进行排序?并且每个数都小于1千万。实际上这个需要1.25MB的内存空间(这里所说的空间是考虑用位图表示法时,每一位代表一个数,则1千万/(1024*1024*8) 约为1.25MB  )。        1MB总共有838,8608个可用位。所以估计也可以在1MB左右的空间里面进行排序了。 二,分析:         1)基于磁

小田的专栏 6982

编程珠玑——第一章

问题描述 输入:一个最多包含n个正整数的文件,每个数都小于n,其中n=10^7。如果在输入文件中有任何整数重复出现就是致命错误。没有其他数据与该整数相关联。 输出:按升序排列的输入整数的列表。 约束:最多有(大约)1MB的内存空间可用,有充足的磁盘空间可用。运行时间最多几分钟,运行时间为10秒就不需要进一步优化了。 程序设计 在这里书中给出了三种解决方案: (1

love_bluesky的专栏 809

编程珠玑(1)

 这周借了本 “编程珠玑”,书不大,200多页,本以为能一周看完的,结果看完第1章就头大了。在此做点笔记,说不定找工作用得上。第1章,位图排序,一位代表一个数(如a[10]=1 表示数10存在)问题里面还有一个 选择问题,即n个数里随机取k个不同的数。开始看到题目的答案就蒙了,后来想想其实很简单。设数组为a[0]...a[n-1]1、j=n2、i=ran(0,j)     //0..j中随

ipiggg的专栏 2318

2019.1.31 自主训练日志

训练第十一天,今天收获颇丰,先来说一下51nod上AC的题目,好事成双、字典序。代码就不展示了,算法简单,属中下难度的题目,相较与那些一眼看上去就会的题目有许多细节上的要求,好事成双的解题思路就是输入数组,然后依次遍历,比较数量关系,计数。但是输入数组长度并不确定,题目中说的是以输入0为结束标志,可在输入样例中并没有0,所以这困扰了我很久,最后试着提交了一遍,才发现输入样例是错的 (...

qq_43627094的博客 221

位向量

看了编程珠玑第一章练习题第二题,关于位向量使用逻辑运算符实现的问题。 首先,位向量不明白:位向量是一种高效的整数结构,每一个32位的整数通过设置或清除它的某一位,可以保存32个数。如果是一个数组,则可以存更多的数。题目意思是使用一个整数表示32个数,可以使多个整数组成的数组,如int a[2]表示两个整数,位向量表示64个数;目前我以为这个主要用来排序,以后有新功能再修改。 其次,编程珠玑给...

weixin_30341735的博客 78

编程珠玑 第一章第9题 空间换时间的数据结构问题

One problem with trading more space to use less time is that initializing the space can itself take a great deal of time. Show how to circumvent this problem by designing a technique to initialize an

坚持 728

编程珠玑》读解 一

编程珠玑》读解 一1. 需求分析 1. 需求分析 对于一个问题,往往要分析两层面的需求: 表需求:题目直接给出的。 里需求:对表需求进一步分析得出的问题本质。 感觉两者差不多?其实不然,从对于表需求的分析得到里需求的过程,是十分关键的。我个人称之为一种不择手段的解决问题方式。所谓“不择手段”,是指在表需求确定的情况下,通过尽可能多地删除非本质条件而得到里需求。 之所以要得到里需求,是因为仅依...

mmountains的博客 322

编程珠玑(二)字符串左旋

编程珠玑第二章的内容,有些内容没有看明白作者的意思。下面是向量左旋和变位词的问题。 一、将一个n元向量左旋转i个位置。例如当N=8,i=3时,向量abcdefgh旋转为defghabc。 这个题目编程之美也有2.17节数组的循环移位和3.1节字符串移位包含的问题。总结下,大概有5种解法,但是编程珠玑上有两种不是很明白,简单介绍下三种算法。 第一种算法比较直接,可以写一个每次都向左移动一位,移

胜利者的经验并不复杂,那就是寻找人生的关键点,并在关键时刻竭尽全力 1260

扫描算法 编程珠玑

编程珠玑第八章,maxsofar保存的是第i个元素之前的最大子数组和 maxsofar=0 maxendinghere=0 for i=[0,n) maxendinghere=max(maxendinghere+x[i],0) maxsofar=max(maxsofar,maxendinghere) for(int i=0; i<len; ++i ) {

john_and_betty的专栏 600

编程珠玑》高清pdf版

下载地址:网盘下载 作者简介 编辑 Jon Bentley是位于新泽西州Murray Hill的朗讯贝尔实验室计算机科学研究中心的技术委员会委员,Jon自1998年就成为Dr. Dobb's Joumal杂志的特约编辑,他的“编程珠玑”专栏多年来一直是顶级学术杂志Communications of the ACM最风行的特色专栏之一,而本书正是...

weixin_30918633的博客 3595

书籍-Jon Bentley《编程珠玑(续)》

编程珠玑(续)》延续了第一部的写作风格,但更加深入地探讨了编程实践中的高级主题。全书分为三个主要部分:编程实践篇涵盖文档编写、算法设计、编程技巧、性能优化、代码调试和测试策略;高级主题篇深入探讨数据结构进阶、并发编程、内存管理、网络编程和可移植性设计;案例研究篇通过小型编译器、数据库系统、操作系统组件和网络应用四个实际项目,展示复杂系统的设计思路和实现细节。本书强调工程化思维、性能意识、质量保障和持续学习,帮助读者提升系统设计能力和工程实践水平。

d3y1`5 81_09 657

编程珠玑 求解最大字串和

  编程珠玑8.4节讲扫描算法,我看了半天都没看明白,最后自己写了一遍,终于搞懂了,把它记下来,以免今后忘了。 首先,书上的算法是这样写的: ? 1 2 3 4 5 maxsofar = 0 maxendinghere = 0 for i=[0 n)     maxendinghere = max(maxendinghe...

test_touch的专栏 196

1. 编程珠玑笔记一开篇

1.          编程珠玑笔记一开篇 从事于IT行业,如果不会编程,那蛤蟆只能呵呵了。 有些人将编程认识为敲字,所以一直是码农。有些人将编程认识为COPY,所以一直是搬运工。我们不是工程师,我们只是IT的搬运工~ 其实编程可以不一样,是一个洞察力和创造力的集合。需要我们不停磨练编程技巧和基本的设计原理。  欢迎转载,转载请标明出处: 1、     开篇 是一个外部排序的问题,题目

badman250的专栏 3万+

编程珠玑第一章-位图压缩存储

  位图 可以对数据进行压缩存储和快速排序,第一、要求集合中所有元素不重复(如果,要使用位图存储含重复元素的集合,需要设计更加复杂的位图结构表);第二,要求存储数据集合限制在较小的范围,如果有个别数据非常大,导致存储位图的集合也非常大,不一定节省空间;第三,对于 结合中的每条数据项,只包含单一的一个整数。   本文主要对编程珠玑第一章,使用位逻辑运算(与、或、移位)来实现位向量所给答案进行解释。 #define BITSPERWORD 32 //要存储元素所要占的位数 #define SHIFT 5//除数

huhu123444的博客 385
上一篇: 归并排序算法解析
下一篇: 编程珠玑 第一章习题1
yousir1988
博客等级 码龄18年 5粉丝 9原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值