【编程珠玑-读书笔记】用位图解决排序问题--仔细分析问题的重要性

开始读《编程珠玑》,刚看完开篇就觉得很开心。

作者从“A Friendly Conversation”讲起,大概是这样子的:

一个programmer问作者:“How do I sort a disk file?”

于是作者简要介绍了一下如何在磁盘中实现Merge Sort,并建议他先钻研下算法课本。然而programmer关注的是如何解决问题,而不是进一步学习。流行的磁盘排序程序大约10多个函数,200行程序代码,实现和测试这部分代码估计不超过1星期。

进一步的对话中,作者了解到,排序的文件包含至多10000000个记录,每条记录都是一个7位整数,数字不重复。而且至多只有1MB的可用主存。

于是问题开始清晰了,因为是整数排序,所有需要的代码量相应减少,执行速度也快了很多,但是调试仍需要一定时间。

第二个方案则是,用40个通道依次将整数读到主存中并排序输出(用32位整数表示每个号码,1MB空间可以存储250000个号码。)在主存中,快排效率是很高的,而且代码简单。

对比上述两种方案,第一种从输入中一次性读取文件,然后在工作文件的辅助下进行排序(工作文件会进行多次读取与写入操作),之后对文件一次性输出。

第二种则需要多次读取输入文件,不使用中间文件。只进行一次输出文件操作。

是否有第三种方法,能够结合以上两者的优势->一次性读取,不使用中间文件呢?

只有当输入文件的所有整数都可以存放(或者说,表示)在可用的主存空间内时,我们才可以实现第三种。

于是问题变为:如何将至多一千万个不同整数表示在大约八百万可用的比特中。

位图

简单的来讲,我们可以使用一个20位的字符串来表示一个小于20的非负整数集合,例如集合{1,2,3,5,8,13}表示为:

0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0

由于7位十进制数表示了一个小于千万的数字,所以我们可以使用一个具有一千万位的字符串表示该文件,当且仅当整数i在该文件中,第i个位才设为1。

算法:

for i = [0,n)
    bit[i] = 0
for each i in the input file
    bit[i] = 1
for i = [0,n)
    if bit[i] == 1
        write i on the output file

位图局限性:

输入范围相对要小一些,不能包含重复数据,没有数据与整数记录相关联。

感言

从最初的磁盘归并排序,到主存的快速排序,再到位图,最后使用位图这一点让我眼前一亮。前两种方法一般情况下都很容易想到,但是其简洁程度远比不上位图的解决方法。从本例中也看出,对问题的描述和定义是如此的重要。如作者所说:“Defining the problem was about ninety percent of this battle!”

如果没有后面的对话,问题仅仅是“How do I sort a disk file?”这无疑是绕了许多弯路。

位图数据结构有其局限性,也有其奇妙之处,我们需要做的是在适当的问题中选取适当的数据结构,灵活应对~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值