位图算法的应用

位图的应用

编程珠玑 Chapter1

位图位向量图作为一个集合,表示的这样的一个数据结构:

          用字符串 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 表示集合 {1,2,3,5,8,13}.

    位图的应用需要数据有如下的特性:

         1.输入数据限制在相对较小的范围内;

         2.数据没有重复;

         3.除了单一整数外,没有任何其他关联数据.

    但很可惜的是,大多数待排序数据没有这些特性(就是说这些特性在大多数情况下是很难满足的).

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

解题报告:

拥有库的语言,C/C++/JAVA都是很好的选择,由于目前只会C++,因此对于我来说别无选择. 而对于C++,实现排序的库有太多的选择,典型的有STL中的stdlib.h中的qsort和algorithm中的sort.对于这两者的区别,在这里不想多谈(其实我并不清楚,大概了解的是stdlib是C的产物,而algorithm的后代,不过,sort在使用上比较简单).

习题二 如何使用位逻辑运算(例如与、或、移位)来实现位向量

解题报告:

一开始当然没有想到要用位逻辑运算来实现位向量,而是用十进制来实现(这是理所当然的事)。

用一个一维数组a[10000000]来存储至多1E7个号码,考虑整数m,一旦发现这个号码,根据我们的算法,应当置a[m]=1.

好的,一切看起来都如此完美,简单的算法,出色的时间效率,差强人意的空间效率.但上机起来就不是这回事了:

但是美好的想法在现实面前是如此的脆弱,这段代码在运行的时候出错了,原因是数组越界.好吧,现在我可以承认,数组开到1E7是不现实的,这该如何是好?

现在是时候回到位逻辑运算了,这是一种模仿计算机底层二进制运算的运算方法,十分高效,但是第一次看上去会显得晦涩难懂,等到将它与十进制运算联系起来后,会发现它相当有用.

整个的思想是,a[10000000]显得太过巨大的原因是每一个元素a[i]只保留了一个bool值或者是一个整型值0或1,如果我们把每一个元素包含的内容扩充,使之保留尽可能多的号码是否存在的信息,那么数组范围会得到明显的下降.

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

现在问题的关键是,如何用位逻辑运算来表示这种操作. 关于位逻辑运算的知识,你应当去参考手头的C++教材,因为在这里我无法讲的比教材更好:

重要的是要从十进制运算的思维转化为二进制运算,位逻辑运算不过是工具而已.

下面是一个位运算的类:

 

习题三 在你自己的系统上实现位图排序并度量其运行时间

解题报告:

为什么说这个算法时空效率达到极致呢?我们对100万个不重复的正整数(1000,0000以内)的文件进行测试:

 

系统排序

C++/STL.set

C++/sort

C++/位图

总时间(s)

89

38

12.6

10.7

计算时间(s)

79

28

2.4

0.5

内存使用(MB)

0.8

70

4

1.25

(本测试数据是在较旧的电脑上测试的,但还是体现性能的差距)
第一行是总时间,第二行的计算时间是总时间减去数据读取耗时10.2秒。虽然通用C++程序使用内存和CPU时间是专用C++程序(C++位图)的50倍,但是它的使用仅需要一半的代码,并能很容易扩展到其他问题上,这也是专用C++程序最大的缺点吧。

 

原文链接:http://knightsgang.spaces.live.com/Blog/cns!5536415C9770F9BF!144.entry

发布了30 篇原创文章 · 获赞 66 · 访问量 65万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章