算法是计算机科学领域最重要的基石之一,但却受到了国内一些程序员的冷落。许多学生看到一些公司在招聘时要求的编程语言五花八门就产生了一种误解,认为学计算机就是学各类编程语言,或者认为,学习最新的语言、技术、标准就是最好的铺路方法。其实你们都被这些公司误导了。编程语言虽然该学,可是学习计算机算法和理论更重要,由于计算机算法和理论更重要,由于计算机语言和开发平台突飞猛进,但万变不离其宗的是那些算法和理论,例如数据结构、算法、编译原理、计算机体系结构、关系型数据库原理等等。在“开复学生网”上,有位同窗生动地把这些基础课程比拟为“内功”,把新的语言、技术、标准比拟为“外功”。成天赶时髦的人最后只懂得招式,没有功力,是不可能成为高手的。 html
当我在1980年转入计算机科学系时,尚未多少人的专业方向是计算机科学。有许多其余系的人嘲笑咱们说:“知道为何只有大家系要加一个‘科学’,而没有‘物理科学系’或‘化学科学系’吗?由于人家是真的科学,不须要多此一举,而大家本身心虚,生怕不‘科学’,才这样此地无银三百两。”其实,这点他们完全弄错了。真正学懂计算机的人(不仅是“编程匠”)都对数学有至关的造诣,既能用科学家的严谨思惟来求证,也能用工程师的务实手段来解决问题——而这种思惟和手段的最佳演绎就是“算法”。
记得我读博时写的Othello对弈软件得到了世界冠军。当时,得第二名的人认为我是靠侥幸才打赢他,不服气地问个人程序平均每秒能搜索多少步棋,当他发现个人软件在搜索效率上比他快60多倍时,才完全服输。为何在一样的机器上,我能够多作60倍的工做呢?这是由于我用了一个最新的算法,可以把一个指数函数转换成四个近似的表,只要用常数时间就可获得近似的答案。在这个例子中,是否用对算法才是可否赢得世界冠军的关键。
还记得1988年贝尔实验室副总裁亲自来访问个人学校,目的就是为了想了解为何他们的语音识别系统比我开发的慢几十倍,并且,在扩大至大词汇系统后,速度差别更有几百倍之多。他们虽然买了几台超级计算机,勉强让系统跑了起来,但这么贵的计算资源让他们的产品部门很反感,由于“昂贵”的技术是没有应用前景的。在与他们探讨的过程当中,我惊讶地发现一个O(n*m)的动态规划(dynamic programming)竟然被他们作成了O(n*n*m)。更惊讶的是,他们还为此发表了很多文章,甚至为本身的算法起了一个很特别的名字,并将算法提名到一个科学会议里,但愿能获得大奖。当时,贝尔实验室的研究员固然绝顶聪明,但他们全都是学数学、物理或电机出身,从未学过计算机科学或算法,才犯了这么基本的错误。我想那些人之后不再会嘲笑学计算机科学的人了吧!程序员
有人也许会说:“今天计算机这么快,算法还重要吗?”其实永远不会有太快的计算机,由于咱们总会想出新的应用。虽然在摩尔定律的做用下,计算机的计算能力每一年都在飞快增加,价格也在不断降低。可咱们不要忘记,须要处理的信息量更是呈指数级的增加。如今每人天天都会创造出大量数据(照片,视频,语音,文本等等)。日益先进的纪录和存储手段使咱们每一个人的信息量都在爆炸式的增加。互联网的信息流量和日志容量也在飞快增加。在科学研究方面,随着研究手段的进步,数据量更是达到了史无前例的程度。不管是三维图形、海量数据处理、机器学习、语音识别,都须要极大的计算量。在网络时代,愈来愈多的挑战须要靠卓越的算法来解决。
再举另外一个网络时代的例子。在互联网和手机搜索,若是要找附近的咖啡店,那么搜索引擎该怎么处理这个请求呢?最简单的办法就是把整个城市的咖啡馆都找出来,而后计算出它们的所在位置与你之间的距离,再进行排序,而后返回最近的结果。但该如何计算距离呢?图论里有很多算法能够解决这个问题。
这么作也许是最直观的,但绝对不是最迅速的。若是一个城市只有为数很少的咖啡馆,那么这么作应该没什么问题,反正计算量不大。但若是一个城市里有不少咖啡馆,又有不少用户都须要相似的搜索,那么服务器所承受的压力就大多了。在这种状况下,咱们该怎样优化算法呢?
首先,咱们能够把整个城市的咖啡馆作一次“预处理”。好比,把一个城市分红若干个“格子(grid)”,而后根据用户所在的位置把他放到某一个格子里,只对格子里的咖啡馆进行距离排序。
问题又来了,若是格子大小同样,那么绝大多数结果均可能出如今市中心的一个格子里,而郊区的格子里只有极少的结果。在这种状况下,咱们应该把市中心多分出几个格子。更进一步,格子应该是一个“树结构”,最顶层是一个大格——整个城市,而后逐层降低,格子愈来愈小,这样有利于用户进行精确搜索——若是在最底层的格子里搜索结果很少,用户能够逐级上升,放大搜索范围。
上述算法对咖啡馆的例子很实用,可是它具备通用性吗?答案是否认的。把咖啡馆抽象一下,它是一个“点”,若是要搜索一个“面”该怎么办呢?好比,用户想去一个水库玩,而一个水库有好几个入口,那么哪个离用户最近呢?这个时候,上述“树结构”就要改为“r-tree”,由于树中间的每个节点都是一个范围,一个有边界的范围(参考:http://www.cs.umd.edu/~hjs/rtrees/index.html)。
经过这个小例子,咱们看到,应用程序的要求变幻无穷,不少时候须要把一个复杂的问题分解成若干简单的小问题,而后再选用合适的算法和数据结构。面试
上面的例子在Google里就要算是小case了!天天Google的网站要处理十亿个以上的搜索,GMail要储存几千万用户的2G邮箱,Google Earth要让数十万用户同时在整个地球上遨游,并将合适的图片通过互联网提交给每一个用户。若是没有好的算法,这些应用都没法成为现实。
在这些的应用中,哪怕是最基本的问题都会给传统的计算带来很大的挑战。例如,天天都有十亿以上的用户访问Google的网站,使用Google的服务,也产生不少不少的日志(Log)。由于Log每份每秒都在飞速增长,咱们必须有聪明的办法来进行处理。我曾经在面试中问过关于如何对Log进行一些分析处理的问题,有不少面试者的回答虽然在逻辑上正确,可是实际应用中是几乎不可行的。按照它们的算法,即使用上几万台机器,咱们的处理速度都根不上数据产生的速度。
那么Google是如何解决这些问题的?
首先,在网络时代,就算有最好的算法,也要能在并行计算的环境下执行。在Google的数据中心,咱们使用的是超大的并行计算机。但传统的并行算法运行时,效率会在增长机器数量后迅速下降,也就是说,十台机器若是有五倍的效果,增长到一千台时也许就只有几十倍的效果。这种事半功倍的代价是没有哪家公司能够负担得起的。并且,在许多并行算法中,只要一个结点犯错误,全部计算都会前功尽弃。
那么Google是如何开发出既有效率又能容错的并行计算的呢?
Google最资深的计算机科学家Jeff Dean认识到,Google所需的绝大部分数据处理均可以归结为一个简单的并行算法:Map and Reduce(http://labs.google.com/papers/mapreduce.html)。这个算法可以在不少种计算中达到至关高的效率,并且是可扩展的(也就是说,一千台机器就算不能达到一千倍的效果,至少也能够达到几百倍的效果)。Map and Reduce的另一大特点是它能够利用大批廉价的机器组成功能强大的server farm。最后,它的容错性能异常出色,就算一个server farm宕掉一半,整个fram依然可以运行。正是由于这个天才的认识,才有了Map and Reduce算法。借助该算法,Google几乎能无限地增长计算量,与突飞猛进的互联网应用一同成长。算法
举一个计算机领域外的例子:在高能物理研究方面,不少实验每秒钟都能几个TB的数据量。但由于处理能力和存储能力的不足,科学家不得不把绝大部分未经处理的数据丢弃掉。可你们要知道,新元素的信息颇有可能就藏在咱们来不及处理的数据里面。一样的,在其余任何领域里,算法能够改变人类的生活。例如人类基因的研究,就可能由于算法而发明新的医疗方式。在国家安全领域,有效的算法可能避免下一个911的发生。在气象方面,算法能够更好地预测将来天灾的发生,以拯救生命。
因此,若是你把计算机的发展放到应用和数据飞速增加的大环境下,你必定会发现;算法的重要性不是在日益减少,而是在日益增强。数据库