一道课本题目引发的思考

  前几天去参加一个面试,看到一道笔试题,大意是:现有一个含有1亿个排好序的手机号码的数组,如何才能够快速查出自己的手机号码是否存在该数组中?我想,不会吧?职位是高级php程序员,居然还问这些课本上的问题?!不过,无论题目是什么,总还是要作答的。

  回来之后我对自己当时的态度有所反省,因我本身不是一个计算机专业出身的人,别人考我课本上的知识也是理所当然。事实上,我也觉得自己理论水平有限,如果说今天还算是入了计算机科学的门的话,无外乎是凭借这几年的知耻而后勇,拾遗补缺。当日的傲慢,确实是要不得。

  但话又说回来,西方计算机开源世界流行甚广的所谓程序员“三美德”,其中一条不就是“傲慢”吗?当然,这是文字游戏,“傲慢”的解释,乃是对自己信心十足,即使把自己的源代码公之于众,让别人抄写学习也不担心别人会因此就超越自己。西方的东西暂时不说,毛主席不也是教导过我们“战略上藐视敌人,战术上重视敌人”吗?这不就是我们一众程序员的写照,没有信心去接受挑战,便无法承受程序员这份工作。有很多技术,今天我已不觉得是什么,但回想当初,不是每一个知识点都是大挑战吗?若当时只看到难,把这些挑战当成强不可破的敌人,还可学得成吗?但到了实际解决问题时,却又要天昏地暗,无光无日地奋斗,重视敌人,才可以真正解决问题,掌握新的技术!

  扯得有点远,回到这条题目上来,这是一道标准的课本题目,题目的标准答案,无疑是Binary Search。还记得我当初弄明白并写出binary search时不知有多兴奋呢!就以本题1亿个搜索单位为例,binary search的最差情况也只是做27次搜索而已,这相对于sequential search的最差情况——1亿次搜索,简直就是魔术!

  但不久就发觉,这个魔术是有限制的,电脑科学家又需针对各个问题,开发出不同的方法。例如,binary search通常适合于静态数据,试想,如何加入一个新的数据呢?若这个数大于原有任何一个数,那便简单,加到最后便可以了;但若相反,新加入的数小于原有任何一个数,那么,1亿个数便要全部向后推一个位,以此类推。对动态数据来说,binary tree才会更有效率。而针对如硬盘这些block device,数据读取必须以block进行,binary tree又改良成B-tree和B+tree,这便广泛应用于各类数据库软件中,著名的ISAM(indexed sequential access method)便是建基于B+tree,MySQL的MyISAM引擎,也是使用B+tree,后来因市场需要才引入了InnoDB,但对于中小型数据库,MyISAM仍是较合适选择。当然最后不能不提AVL tree,这个自动平衡的算法,补足了binary tree的严重缺陷,亦成为了in memory search的其中一个重要选择。

  我坦白,学习AVL tree已经令我有点头昏脑涨了,学是学了,但却没用过。有一位前辈经常教训我说:作为程序员,傲慢是必须的,但千万不要盲目傲慢到去不停重新发明车轮。鲁迅先生所提倡的“拿来主义”今天看来还是有用的。就拿我大部分的编程经验都和MySQL有关这事来说,如果没有一个充分的理由,有什么必要叫我重新写一个数据库软件呢?固然,我现在写出Binary search算法也就几分钟的事,但数据库已提供了更好的解决方案,还需要重新发明车轮吗?事实上,今天主流的编程语言如PHP等都提供了处理数据排序查询问题的API函数,但我们大部分时间还是应当把这类工作交给数据库,例如,MySQL处理这类问题上远比PHP更有效率。记得有一次,要用C#读取一组动态数据到内存中做高速查询,我想这次哥总算是英雄有用武之地了吧?但一搜索.NET的类库,才发现各样工具应有尽有,连Binary search也只不过是Array类的一个方法而已!

  但我心里却始终有个谜,为什么这些方法可以这么神奇?背后的原理又是什么呢?这个谜可以说在我涉猎信息论(Information Theory)时得到了一丝曙光。这门理论一般都认为兴起于1948年,由Claude Shannon发表的一篇名为“A Mathematical Theory of Communication”的论文所提出。现在这门学问已广泛用于前沿科技的研究,由量子物理学到黑洞都用得上。我当然不懂量子物理学,但就信息论在资讯科技上的贡献还是可以讨论一点的。Shannon的其中一个重要贡献就是把热动力学的一个重要概念“熵”(Entropy)引入了信息学中。

  何谓“熵”?“熵”本来是一个系统混乱程度的量度。相对于混乱,就是规律和重复,又或者说规律和重复在某个角度来说是同一个概念。举个例子,自然语言是很有规律的,也就是说重复性很高。今天流行的无损压缩技术,其原理就是针对原有数据的高重复性,对其进行编码,比如一段文本重复出现了某个单词,就可以用一个特定的更简单的符号将该单词进行编码,当文本中大量这样的重复出现的单词都被编码后,原来的数据量得到了压缩,变得更小了,而熵值则增加了。

  可见,数据压缩就是以“熵”来换取空间,提升数据的熵值来减少存储空间的。同样,为什么binary search会比sequential search有效率呢?其实就是我们事先投入了大量的计算力去降低数据的“熵”,简单来说,排序就是使数据没有那么“乱”了,理所当然的,就可以加快查询速度啦!而排序的过程,正是人们通过给“数据”这个系统做功,从而降低系统的熵值——这不正是热力学第二定律的一种阐释吗?

  明白了信息科技和热动力学可以有相通之处又如何?这便令我得出一套思考套路,在理解各样信息科技问题时有所依据。例如,RAID,RAID1不就是通过用两个硬盘存储相同的数据,以增加冗余度(即令熵值下降),进而增加可靠性吗?而代价当然就是额外的硬件投资和重复写入数据的工作和相应的电力和时间资源。

  另一个不太明显的例子就是缓存,例如当我们使用memcached来加快数据读取速度,其代价就是要写额外的代码区检查缓存中是否存在所需的数据,若没有,则需要在从数据库读取的同时,写入一份到缓存中,这也是用额外工作来降低熵值的方法。

  总而言之,明白了熵的原理,便不会再去想世界上存在着免费午餐了。因为任何加速,又或者减少存储空间的手段和算法,必然是以在某些另外的环节降低熵值为代价的。

 

 

 

 

                                                                                                             

posted @ 2014-03-03 11:28  nianjun  阅读(255)  评论(0)    收藏  举报