编程珠玑

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

本文首发于个人博客之编程珠玑,之后会陆续将博客转移至个人博客,期待与各位的交流


这不是一本具体算法的讲解或者代码编写的教程,但是从书中的字里行间,我们可以学到的是更多的软知识:对编程新的认识、更加发散的思维方式、更严格的代码要求、堪比瑞士军刀的小技巧…… 编程也许入门并不难,但是要想真正成为一名优秀的软件工程师,还是需要很多锤炼。内外兼修,方成大器。


基础篇

  • 第一章 开篇

    首先作者提出一个实际问题:

    如何给磁盘的某个文件排序,更具体来说就是是对一个最多包含1千万条记录,每条记录都是7位整数的文件,而且只有1MB的内存可以使用

    从实际问题中提炼出更明确的数学定义:

    输入:一个最多包含n个整数的文件,每个数都小于n,其中n=10^7。可以保证输入文件中不存在重复整数
    输出:按升序排列的输入整数的列表
    约束:1MB左右的内存空间,充足的磁盘存储空间。运行时间最多几分钟,控制在10秒内不再需要进一步优化

    考虑一般的解法,直接读入所有的整数,然后进行快排堆排之类的排序,时间复杂度很明显是O(nlogn),但空间复杂度是O(n),即如果n=10^7时,用4个字节的int型存储每个整数,那么需要的空间是(4*107)/210210=38MB,很显然超出了内存限制,而考虑实际n的大小限制和每个整数只会出现一次的限制,而所谓的排序也只是把从文件中的整数按在1-n内出现的顺序输出而已,因此只要对n之内出现的整数做一下标记最后输出标记过的整数就可以了,考虑到这,位向量(也叫位图)就成了比较合适的数据结构的选择,每个位的0、1值表示一个数字是否出现过,实现的时间复杂度为O(n),空间复杂度为O(n),考虑n取最大值10^7时,需要的空间为107/8/210/210=1.2MB,代码实现如下:

    
    #include <iostream>
    
    
    #include <fstream>
    
    
    #include <bitset>
    
    
    #include <string.h>
    
    
    #define N 1000000
    
    using namespace std;
    
    void intSort(){
       bitset<N> numBits;
       ifstream = testFile("/Users/smy/temp/data.txt");
        string s;
        int count = 0;
        while(testFile >> s){
            numBits[atoi(s.c_str())-1] = 1;
            ++count;
        }
        testFile.close();
    
        for(int i=0;i<N;++i){
            if(numBits[i] == 1){
                cout<<i+1<<endl;
            }
        }
    }
    int main(int argc, const char * argv[]) {
        intSort();
        return 0;
    }

    那么进一步考虑:

    如果严格限制程序占用内存不能超过1M,应该怎么处理?
    如果每个数最多出现10次,又应该如何改动算法?所用存储空间是怎样变化的呢?

    在解决这个实际问题的方案中,我们看到了不同于比较排序的一种排序方式:位向量排序,而且从这个问题中也引出了作者的一些思考和对读者的启示:

    • 做一个”懒”工程师:处理问题时,即便是一看上去就知道解法的问题,不要马上动手编写代码,花些时间去明确问题,抽象问题模型,结合问题的特点去分析,等灵光一现时再动手。作者在解决上题时首先是对问题进行了数学定义,考虑到问题中数据的特点以向量的方式解决了问题并且时间复杂度和空间复杂度都较低。这样的方式不仅能收到更好的编码效果,考虑的情况会更加完善,调试起来的时间也会缩短,而且经过深度思考再动手的印象要深刻的多,等之后再遇到类似的问题时,马上就会涌现解决问题的思路,这样才能积累真正的经验。
    • 时间和空间可以是双赢的:确实很多时候也许我们会在时间和空间之间做折中的选择,但是这种折中一定应该是在我们仔细分析了某方面不能再有改善的情况下,而很多情况下因为自己算法能力的不足和思维能力的局限,也许自己的算法可以在时间和空间双重优化,这就要求一方面自己要深度思考当前算法的优化空间,另一方面可以向更优秀的人请教是否有完全不同但是可以达到更好效果的方法或者对自己算法的建议,如果确实确定要做折中处理的话,要明确问题对时间和空间要求的严格性和最大容忍限度,然后在合理牺牲某方面的前提下向预定目标靠拢。
    • 简单的设计:“设计者确定其设计已经达到了完美的标准不是不能再增加任何东西,而是不能再减少任何东西”,在满足要求的前提下尽量让设计简洁,有利于今后的扩展和排错,“大道至简“,设计需要的也许更多是简洁的美。
  • 第二章 啊哈!算法

    1. 给定一个最多包含m=40亿个随机排列的n=32位整数的顺序文件,找出一个不在文件中的32位整数。在内存足够的情况下如何解决该问题?如果有几个外部的“临时文件“可用,但是仅有几百字节的内存,又该如何处理?
    2. 将一个n元一维向量想做旋转i个位置(如对n=3元向量“abc“,当i=1时,结果为“bca“)
    3. 给定一个英文字典,找出其中的所有变位词集合。(变位词指的包含相同数量相同字母的单词,因为他们通过调整字母的顺序可以变为一个单词所以叫变位词,如”stop”和”tops”和”pots”)

    对于问题1,首先明确一下肯定是存在整数不在文件中的,因为32位整数最多可以表示的数字是2^32=4294967296>4000000000
    (1)在内存充足的情况下,可以用上述位向量的做法,初始化2^32个位为0,每读到一个数字就将对应下标的位数组的值置为1,最后统计值仍为0的元素就是没有出现过的整数,这样的做法时间复杂度是O(2^n),空间占用大约为O(2n/8)B,当n=32时占用空间大小约为2n/8/210/210=512MB
    (2)内存不够有临时文件可以使用时,又该如何做呢?既然有临时文件可以用,那可以将原来大文件中的数字分配到临时文件中,当临时文件的规模够小时再采用上面说的位向量的算法。分配可以采用散列的方法,比如通过简单的模上临时文件的个数将结果相同的聚合到一个文件,判断缺失元素在哪个文件的方法是在向临时文件插入元素的时候统计每个临时文件的数字个数,因为我们是可以知道根据我们选定的散列算法在没有元素缺失情况下的数字个数k的,那么这样就只需要比较散列完成后临时文件的个数与k比较,如果比k小的话那么这个临时文件中就存在缺失元素,接下来以这个临时文件为主文件,再次采用前面所说的散列方法(此时散列算法的参数可能需要调整)如此迭代下去直到限制的内存空间足以承载包含缺失元素的文件规模时,回到第一种情况处理。 可以看到这也体现了二分搜索的思想,只不过是以文件包含的一系列整数为范围,用包含这些整数的文件表示这个范围,通过比较文件中整数个数与期望个数判定缺失元素所在文件范围,从而达到了缩小问题规模的效果将问题转换成内存充足的情况。

    对于问题二,看起来比较简单,代码实现起来也不难,不过作者提供的几个巧妙的算法倒让人耳目一新。
    我一开始的想法是作者所说的“杂技算法“,

    <
编程珠玑:深入浅出的编程经典 本文还有配套的精品资源,点击获取 简介:《编程珠玑》是一本计算机科学的经典之作,由Jon Bentley撰写。书中不仅详细探讨了数据结构和算法,还深入分析了问题解决策略、编程的艺术与技巧,以及性能优化。书中附带源代码分析,帮助读者通过实际案例理解理论与实践的结合,从而提升编程技能和解决问题的能力。 1. 数据结构与算法详解 简介 数据结构与算法是计算机... 阅读详情

相关推荐

编程珠玑 Programming Pearls 第二版(中文版+源代码)

计算机经典书籍——编程珠玑 Programming Pearls

编程珠玑.pdf

编程珠玑,适合于开发人员的一本基础教材,建议可以通读一遍,会有收获的。

编程珠玑 第2版(修订版)_编程珠玑修订_资料_

编程相关文档建议。作者写了编程中的相关注意点,值得一看。在编程中可多注意。

MiMo-VL-7B-SFT与其他开源VLM对比:Llava、Qwen-VL、CogVLM全面评测

在当今快速发展的多模态AI领域,**MiMo-VL-7B-SFT**作为小米推出的开源视觉语言模型,以其卓越的推理能力和视觉理解表现脱颖而出。本文将深入对比MiMo-VL-7B-SFT与当前主流的开源VLM模型——Llava、Qwen-VL和CogVLM,帮助开发者和研究者了解各模型的特点、优势与适用场景。 ## 🎯 核心功能对比:四大开源VLM模型 ### 1. MiMo-VL-7B-SF

gitblog_09741的博客 766

编程珠玑

编程珠玑(第二版)》 Programming Pearls Second Edition “《编程珠玑》第一版是我职业生涯早期阅读过的最有影响力的书籍之一,第一次从该书中学到的许多观点很久以后仍然使我受益匪浅。Jon在第二版中对素材进行了大量更新,这些新例子的新鲜程度给我留下了深刻的印象。” ——Steve McConnell 《Code Complete》等多部畅销书作者如果让

丫猫Johnny的专栏 1404

编程珠玑,字字珠玑

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

DigitalSonic的自留地 287

编程珠玑》摘要

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

DaDianJiShiQi的博客 1269

编程珠玑】陪着奶猫看看书--《编程珠玑》第一章

陪着奶猫看看书–《编程珠玑》第一章 没事吹吹看《编程珠玑》的感受!大家一起讨论讨论!!!

IShadow 1025

编程珠玑》读解 一

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

mmountains的博客 322

学习编程珠玑

      前天晚上将《编程珠玑》随便翻了一下,看了一下标题,怎样给磁盘文件排序。      当时想了一会,没想清楚磁盘文件是什么?怎么排序,昨晚一看,果然里面有大有玄机。通过大师的分析终于搞清楚了里面的概念问题,沿着当时的思路一直走下去。突然被里面的算法吸引住了,独辟蹊径。从来没想到用这样的算法,以前想的可能一直是怎样排序,然后找最优的算法。      第一感受就是被算法所吸引,精妙的算

娃娃鸭的专栏 666

编程珠玑第一章

今天看了编程珠玑,通过自己的思考及从网上查找别人的思路,将第一章的答案整理一下。

dongqifan的专栏 740

编程珠玑(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的专栏 2319

送5本《编程珠玑 第二版》

文末赠书说起IT编程经典,我们总是绕不开《编程珠玑》。距离这本书首次问世已有近40年之久了,中文版也已经出版近15年。以计算机和互联网的发展速度而言,别说是40年,哪怕只有几个月也足够让一项技术更新得“面目全非”。那么这一本1986年就面世的《编程珠玑》,为何至今仍能畅销全球,且被业内大牛誉为编程“奇书”?对于这个问题,我们邀请了一位老朋友——资深技术人高博,来和大家聊聊《编程珠玑》。▲ 点击图片...

a934079371的博客 283

编程珠玑之scaffolding

   最近在看《编程珠玑》一书,在书中第五章,出现了scaffolding一词,见中文版书中翻译为“脚手架”,不解其意。在书中的原句为“Wise programmers instead build scaffolding to give them easy access to the function.”,"Once we have the code ,well probe it with sc

Leatinfy--☆Dream and dreaming☆ 3425

编程珠玑》作者Jon Bentley推荐的书

编程珠玑》的作者Jon Bentley可以算是博览群书了,在这本书里涉及的书据鄙人不完全统计就有17本之多——而且本本经典,所以无聊做了一个list。    很遗憾,某些经典书如《设计模式》、《重构》等当时没有出版,所以没有上榜。我想如果作者准备出第三版的话,一定会增加相应的章节并提到这些书或作为Further Reading推荐给读者。 *********************下

Ccrazyman的专栏 900

编程珠玑》之位图技术

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

sf_jiang的博客 685

编程珠玑学习资料

编程珠玑】鸟瞰 --- 编程珠玑 (2012.8.7) 序:刘翔今天再一次倒在起跑线上,我作为翔子的Fans,盯着屏幕看刘翔起跑,当他第一个栏摔倒时,我的心碎了,情绪异常低落,久久难以平复。然后给老爸发短信抱怨:刘翔退赛了,为什么又是因伤退赛?我难受。老爸轻描淡写:没办法,这就是竞技体育,有起有落才是人生。          希望刘翔身体无大碍,早日康复。翔子:咱是纯爷们,这届不行,咱

leiyifight的专栏 992
上一篇: Android中的BLE
下一篇: 并发编程之同步互斥篇
会敲代码的咩
博客等级 码龄12年 39粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值