您的位置:首页 > 编程语言

编程珠玑---第一章 阅读笔记

2011-05-26 17:19 218 查看
昨天看了编程珠玑的第一章和课后题目,收获很大,大概总结下。
第一章首先提出了一个问题:如果有一个文件最多n(n=1000w)个整数,这些整数都<n, 并且这些整数是不重复的,但是是无序的,如何使用一种快速的方法将这些整数进行排序?同时要求内存最多是1M,即空间有要求。
问题就这样被提出,书中给出了好几种方法。
第一种,很容易想到的就是使用归并排序,时间复杂度是nlgn。但归并排序需要把数据全部读入内存,1000w个整数的大小是1000w*4/(1024*1024)大约是40M(假设一个整数是4个字节),显然不能将全部数据读入内存。
第二种方法是这样描述的:因为这些整数是<1000w的,那么可以将这些整数分成40组,分别是[0-249999]  [250000-4999999]  … [9750000-9999999],然后遍历40次整数序列,第一次找出范围在[0-249999]的,第二次找出范围在[250000-499999]的。。。第40次找出范围在[9750000-9999999]的。这样时间复杂度是40n,空间复杂度是n/40,比归并要好点。当然也可以把范围扩大或者缩小,比如两次遍历,第一次范围是[0-4999999],第二次是[5000000-9999999],这样空间复杂度会变大。
书中第三种方法应该是很巧妙的,而且很有学习价值,称为位图法。其思想是用1位来表示[0~n-1]中的整数是否存在。1表示存在,0表示不存在。这样的话进行一次遍历,就可以进行排序了,而且空间复杂度是n/(8*1024*1024)。例如对于20个数来说,如果集合是这样的{1,2,3,5,8,13}即表示共6个数,都小于20.那么其位图表示法如下:01110100100001000000.即如果这个数在序列中,那么用1表示,如果不在用0表示,这样就简单的把序列进行了排序,不得不赞这种思想。
这种思想的伪代码如下:
for (i  in  [0~n-1])  bit[i] = 0; //初始化为0
for(i  in [0~n-1])
if (i in input file)(判断i是否在输入中,如果在则设置bit[i]为1)
      bit[i] = 1
for(i  in [0~n-1])
if(bit[i] == 1)(输出i)
     output i
 
这种思想的在利用的时候需要考虑一些问题:
1、需要输入的数是在小于n的情况下,即要有一个范围
2、输入的数是没有重复的,当然如果有重复也是可以的,比如重复次数不超过m次的话,那么可以用lgm位来表示1个数
章节后面有一些习题,也是很好的。
1、如果整数有1000w个的话,其实1000w位的空间是大于1M的,那么如何处理呢?
可以利用第二种思想和位图思想进行结合。
对数据进行两次遍历,第一次找出[0~4999999]的数据,并且用位图进行表示,第二次找出[5000000~9999999]的数据用位图表示,这样就会将空间降到了一半。
编程珠玑第一章主要是这个位图的思想,以后考虑问题尽量想到这样的思想,利用空间换时间,而且尽量减少空间的使用。哈哈~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: