【读书笔记】《编程珠玑》第一章之位向量&位图
此书的叙述模式是借由一个具体问题来引出的一系列算法,数据结构等等方面的技巧性策略。共分三篇,基础,性能,应用。每篇涵盖数章,章内案例都非常切实棘手,解说也生动有趣。
自个呢也是头一次接触编程技巧类的书籍,而且算法数据结构方面的知识储备实在是薄弱,这么看来,纯粹找虐啊orz。今此行为,歇业养伤,实属无聊。也可说是自打毕业后,看书如打仗,自视身处“安安稳稳的和平年代”,闲来了也就闲着,忧患意识甚少,有也退退缩缩。话说回来,这本书不像CLRS那种难打的硬仗(现在想想都脑仁疼啊),《Programming Pearls》这么个好对手,排烦解闷也正好练练身手!
废话了一大堆,嘿嘿,看官轻拍。那下面就来看看第一章讲了些啥~
问题
怎样给一个最多包含1千万条记录且每条记录都是7位的整数的磁盘文件排序?
准确描述
这里书本对问题抽象出了精确的描述:
输入:一个最多包涵n个正整数的文件,每个数都小于n,其中n=10^7。如果在输入文件中有任何整数重复出现就是致命错误。没有其他数据与该整数相关联。
输出:按升序排列的输入整数的列表。
约束:最多有(大约)1MB的内存空间可用,有充足的磁盘存储空间可用。运行时间最多几分钟,运行时间为10秒就不需要进一步优化了。
解决方案
归并排序。联想下归并排序的缺点:需要O(n)的辅助空间,可知他必将多次的多写一块额外的工作文件or内存。优势:只需读取一次。劣势:需要数次操作额外文件。
分批读入数据,然后使用快速排序。每个整数用32位即4字节表示最多可表示带符号的2^31-1>9 999 999,计算10^7/(10^6/4)可得,40次读取排序可以达到目标。优势:快。劣势:多次读取数据,多趟算法。
使用位图数据结构。这个一个(10^7/32 + 1) 行 (32) 列的大表:
31 30 ... 1 0 31 30 ... 1 0 ...... 31 30 ... 1 0 31 30 ... 1 0
如果数据是{2,3,5},那么第一行上就会是:0000 0000 0000 0000 0000 0000 0010 1100。很明显的,文件里所有的整数都可以在这张表里找到对应的位置,聪明如你,这就是一个大小为10^7/32 + 1的int[],具体的算法是这样的:
package chpt1; import java.util.List; /**
* Created by wqi on 2016/10/22.
*/
public class BitSort {
// 位向量,也可称作位图,这里为了形象化,取作bitMap.
private int[] bitMap; // i >> 5即每32个数为一组,也就是数组重的一个int元素。 i & 0x1f 相当于取该数对32取模,就找到了该数对应的位,|= 即为置1。
private void set(int i) {
this.bitMap[i >> 5] |= (1 << (i & 0x1f));
} // 和set()本质上的区别就是 &= 将该数对应的位置0
private void clr(int i) {
this.bitMap[i >> 5] &= ~(1 << (i & 0x1f));
} // 返回该数对应的位为1或为0
private int test(int i) {
return (this.bitMap[i >> 5] & (1 << (i & 0x1f)));
} public void sort(List<Integer> list) {
this.bitMap = new int[list.size() / 32 + 1]; for (int i = 0; i < this.bitMap.length; i++) {
clr(i);// 第一阶段将所有的位都置为0。
}
for (int i = 0; i < list.size(); i++) {
set(list.get(i));// 第二阶段读入文件中的每个整数来建立集合,将每个对应的位都置为1。
}
for (int i = 0; i < list.size(); i++) {
if (test(i) == 1){
// 第三阶段检验每一位,如果该位为1,则输出这个数。
}
}
}
}
优势:只需要读取一次文件数据,且不需要额外文件。而且使用的是基本的位操作,速度会更快。劣势:没有,这算法相当友好。
总结
这一章在英文原版中名为 Cracking the Oyster ,直译为「美妙的(也可作开裂的)牡蛎」。和开篇概览中提到的『对实例研究的深入思考不仅很有趣,而且可以获得实际的益处』很贴切,牡蛎多鲜啊,pearls 的美也很直观的看到。再扯句题外话,貌似在西方国家 Oyster 这个词的意味是很好的,沙翁的台词中有 the world is my oyster 意译可表示成——我可以为所欲为啦。
位图这种数据抽象确实很有趣!巧妙的解决了这种看上去很乍乎的大数据问题。在网上也了解到,很多时候在处理大批量数据时,都可以考虑使用该数据结构,这点往后有待补充,希望在这再写几篇做到『举一隅,不以三隅反』。另外,针对位图这一数据概念,Java已经有操作起来非常简单的实现了,就是BitSet(),该集合类初始范围在0~63(JDK Version: 1.8.0_101),如果这时候BitSet().set(64),它会自动扩容至当前容量的翻倍,也就是*2,在这即0~127。
就先写到这,2016年10月22日16:56:01。课后习题部分是很依赖对前文的理解,且变化不是太大,书后答案代码部分大都是用C/C++写的,但只会Java的我看起来也不麻烦(看到qsort好羡慕C系的程序员啊),明天看看有没有有意思的题目再补充吧。#明日债明日还#
;-)
【读书笔记】《编程珠玑》第一章之位向量&位图的更多相关文章
- 编程珠玑第一章的算法,Java实现,通俗易懂
该算法也就是所谓的位图算法,用一个int表示32位,也就是实际值为1~32的数. 按照书里说的, 该算法只适合内存有限,而磁盘和时间不限,且数字在1~MAX之间不重复的排序. package demo ...
- 读书笔记http之第一章
http TCP/IP协议各层: 应用层 决定了向用户提供应用服务时通信的活动. 比如 : FTP(FileTransferProtocol,文件传输协议)和DNS(DomainNameSystem, ...
- 《Android开发艺术探索》读书笔记 (13) 第13章 综合技术、第14章 JNI和NDK编程、第15章 Android性能优化
第13章 综合技术 13.1 使用CrashHandler来获取应用的Crash信息 (1)应用发生Crash在所难免,但是如何采集crash信息以供后续开发处理这类问题呢?利用Thread类的set ...
- SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)
SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1 ...
- 《Android开发艺术探索》读书笔记 (3) 第3章 View的事件体系
本节和<Android群英传>中的第五章Scroll分析有关系,建议先阅读该章的总结 第3章 View的事件体系 3.1 View基本知识 (1)view的层次结构:ViewGroup也是 ...
- JavaScript DOM编程艺术第一章:JavaScript简史
本系列的博客是由本人在阅读<JavaScript DOM编程艺术>一书过程中做的总结.前面的偏理论部分都是书中原话,觉得有必要记录下来,方便自己翻阅,也希望能为读到本博客的人提供一些帮助, ...
- 《Android开发艺术探索》读书笔记 (9) 第9章 四大组件的工作过程
第9章 四大组件的工作过程 9.1 四大组件的运行状态 (1)四大组件中只有BroadcastReceiver既可以在AndroidManifest文件中注册,也可以在代码中注册,其他三个组件都必须在 ...
- [书籍翻译] 《JavaScript并发编程》第一章 JavaScript并发简介
> 本文是我翻译<JavaScript Concurrency>书籍的第一章,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript并 ...
- [Java编程思想] 第一章 对象导论
第一章 对象导论 "我们之所以将自然界分解,组织成各种概念,并按其含义分类,主要是因为我们是整个口语交流社会共同遵守的协定的参与者,这个协定以语言的形式固定下来--除非赞成这个协定中规定的有 ...
随机推荐
- EXCEL 2010学习笔记 —— 数据透视表
今天整理一下EXCEL2010 数据透视表的课程笔记,数据透视表可以对多组数据进行统计和整理,是一种基本的数据可视化工具. 记录6个方面的总结: 1.创建数据透视表 2.更改数据透视表的汇总方式 3. ...
- DuBrute 3.1
PS:转载自小残博客. 今天发现时隔很久的DuBrute竟然更新了,为此我在分享给大家,软件我没测试效果,使用过的朋友或许很清楚,不会太差! 曾几何时,小残也在用DUbrute爆破工具,且玩的不亦乐乎 ...
- Web APP 之rem的使用
移动端web app的开发,之前开发直接使用px像素做单位,这样子做对于传统的PC端开发来说,个人比较习惯,但是对于移动端在来,有说逞强.最明显是切图效果与设计师想达到的效果有些差距,比如<he ...
- bzoj4025 二分图
支持加边和删边的二分图判定,分治并查集水之(表示我的LCT还很不熟--仅仅停留在极其简单的模板水平). 由于是带权并查集,并且不能路径压缩,所以对权值(到父亲距离的奇偶性)的维护要注意一下. 有一个小 ...
- 文件权限:普通(r、w、x)和特殊(s、t)
linux中,常常涉及到权限的问题.文件的权限有3组,owner,group,other,每一组都有rwx三种设置.r(4):可读:w(2):可写:x(1):可执行.我们在执行shell命令ls - ...
- 第一天--html
<!Doctype html><html> <head> <meta charset="UTF-8"> ...
- [Android Pro] 完美Android Cursor使用例子(Android数据库操作)
reference to : http://www.ablanxue.com/prone_10575_1.html 完美 Android Cursor使用例子(Android数据库操作),Androi ...
- Css样式表【边界边框】【列表方块】
一.如何给div加边框?[边界边框] 我们先做一个整个边框,并附加成绿色的边框. ①使用属性border进行设置. →→ ②也可以单独更改某个边的边框线的颜色,利用border属性更改. 如果将div ...
- centos6.5安装elasticsearch
java下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htmles下载地址 : ...
- Linux C编程学习之开发工具3---多文件项目管理、Makefile、一个通用的Makefile
GNU Make简介 大型项目的开发过程中,往往会划分出若干个功能模块,这样可以保证软件的易维护性. 作为项目的组成部分,各个模块不可避免的存在各种联系,如果其中某个模块发生改动,那么其他的模块需要相 ...