Updated(2008-7-24):更新见正文部分,有标注。
其实下文的绝大部分内容对所有学习都是同理的。只不过最近在正儿巴经地学算法,而后者又不是好啃的骨头,所以平时思考总结得就自然要比学其它东西要多一些。
问题:目前几乎所有的算法书的讲解方式都是欧几里德式的、瀑布式的、自上而下的、每一个推导步骤都是精准制导直接面向目标的。由因到果,定义、引理、定理、证明一样不少,井井有条一丝不乱毫无赘肉。而实际上,这完全把人类大脑创造发明的步骤给反过来了。看起来是阳关大道,实际上车马不通。
而对读者来说,这就等于直接告诉你答案&做法了,然后让你去验证这个答案&做法是可行&成立的。而关于答案&做法到底是怎么来的,从问题到答案之间经历了怎样的思维过程。却鲜有书能够很好的阐释。就我有限的阅(算法)书经验,除了波利亚的《怎样解题》还算合格之外(也并非最理想),其它的(包括有名的《算法导论》、《如何解题:现代启发式方法》、《Algorithms》、《编程珠玑》,甚至TAOCP——公平地说由于高老大对算法领域历史了解得非常通透,所以许多地方能够从原始脉络来讲述一个问题,譬如令人印象深刻的从竞赛树到堆的讲解就寥寥一页纸道出了堆这个数据结构的本质来,而像刚才列的几本有名的书却都没有做到),在思维的讲述上都算不上合格(当然不是说这些书没有价值,作为知识性的参考书籍,它们将知识整理出系统结构,极大的便利了知识的掌握,就像《什么是数学》所做的工作一样),为什么我这么说呢,因为我发现每每需要寻找对一个算法的解释的时候,翻开这些书,总是直接就看到关于算法逻辑的描述,却看不到整个算法的诞生过程背后的思想。
我们要的不是相对论,而是诞生相对论的那个大脑。我们要的不是金蛋,而是下金蛋的那只鸡。
Update(2008-7-24):收到不少同学的批评,想来这个开头对一些著作的语气过重了,实际上,注意,我完全不否认这些著作的价值,我自己也在通过阅读它们来学习算法,并且有很多收获。这篇文章更多的只是建议除了阅读这些著作之外还需要做的功课。此外,对于这类知识讲述(欧几里德)方式的批判西方(尤其是在数学领域)早就有了,早在欧拉和庞加莱的时候,他们俩就极其强调思维的传授,欧拉认为如果不能传授思维,那数学教学是没意义的。而庞加莱本人则更是对数学思维有极大的兴趣和研究(我前阵子在讨论组上还转载了一篇庞加莱的著名演讲,就是说这个的,参见这里)。我只是在说目前的算法书没有做到思维讲述的层面,因此建议阅读这些书之余应该寻找算法的原始出处,应该寻根究底,多做一些功课,知道算法到底是怎么诞生的,并且我说明了为什么应该知其所以然,有哪些好处(见下文),我还给了几个例子譬如红黑树作者讲红黑树的,g9讲后缀树的,以及Knuth讲heap的。唉,其实挺正统的观点,授人以渔,不管是东方西方都有类似的古老谚语。而我只是从认知科学的角度加了点解释,windstorm称之为“解释文”。而已。可惜被开头的语气搞砸了,算了,既发了也就不改了。
为什么会这样,其实是有原因的。
我们在思考一个问题的过程中有两种思维形式:
- 联想:这种思维某种程度上可以说是“混乱”的(虽然从一个更根本的层面上说是有规则的),所谓混乱是指很多时候并不确定联想到的做法最终是否可行,这些联想也许只是基于题目中的某个词语、语法结构、问题的某个切片、一些零星局部的信息。这个过程是试探性的。最后也许有很大一部分被证明是不可行的。很多时候我们解决问题用的都是这种思维,简言之就是首先枚举你关于这个问题能够想到的所有你学过的知识,然后一一往上套看看能否解决手头的问题。这种思维方式受限于人脑联想能力本身的局限性。我在《跟波利亚学解题》中就提到了几个例子。联想本身需要记忆提取的线索,所以受到记忆提取线索的制约,如果线索不足,那怎么也联想不起来。而提取线索的建立又取决于当初保存记忆的时候的加工方法(《找寻逝去的自我》里面有阐述),同时,面对一个问题,你能够从中抽取出来的联想线索又取决于你对问题的认识层度/抽象深度,表浅的线索很可能是无关的,导致无效的联想&试错(《Psychology of Problem Solving》里面有阐述)。总之,联想这个过程充满了错误的可能。
- 演绎&归纳:演绎&归纳是另一种思维形式。它们远比联想有根据。其中演绎是严格的,必然的。归纳也是有一定根据的。在面对一个问题的时候,我们有意无意的对问题中的各个条件进行着演绎;譬如福尔摩斯著名的“狗叫”推理——狗+生人=>吠叫 & 昨晚狗没有叫 => 那个人是熟人。就是一个典型的对问题的各个条件进行演绎的推理过程。还有就是通过对一些特殊形式的观察来进行归纳,试图总结问题中的规律。然而,不幸的是,面对复杂的问题,演绎&归纳也并不总是“直奔”问题的解决方案的。人的思维毕竟只能一下子看到有限的几步逻辑结论,一条逻辑演绎路径是否直奔答案,不走到最后往往是不知道的,只要答案还未出现,我们大脑中的逻辑演绎之树的末端就始终隐藏在黑暗之中。而当最终答案出现了之后,我们会发现,这棵演绎之树的很多分支实际上都并不通往答案。所以,虽然演绎&归纳是一种“必然”的推理,然而却并不“必然”引向问题的结论,它也是试错的,只不过比联想要更为靠谱一些。
鱼是最后一个感觉到水的”,我们感觉不到思维法则本身的存在,我们只是不知不觉运用它。三来,由于我们的目标是问题的解,解才是我们为之兴奋和狂喜的东西,而不是求解的过程,过程只是过程,目的才是目的。这就像一个寻宝者,在漫长曲折的寻宝历程之后,在找到宝藏的时候,他会对宝藏感到狂喜(记得阿基米德的“找到了!”吗?)而迫不及待地要展示出来,而漫长的思考本身却成了注脚。我们是有目的的动物,目的达到了,其它的就相对不那么重要了。最后,对于传授知识的人,也许还有其四:感到介绍思维过程是不相干的,毕竟思维过程并不是算法问题的解,算法问题的解才是算法问题的解。然而不幸的是,忽视到达解的那个过程实际上却变成了舍本逐末。我们看到的是寥寥数行精妙绝伦的算法,然后仰天长叹自己想不出来啊想不出来。为什么想不出来,因为你不知道那短短数行算法背后经历的事怎样漫长的思考过程,如果问题求解是一部侦探小说,那么算法只是结局而已,而思考过程才是情节。
既然认识到,人类解决问题的两大思维方式实际上都是有很大的试错成分的(好听一点叫“探索”),那么就不难意识到,对一个问题的思考过程实际上是相当错综复杂的,而且充满了无效分支——在思考的过程中我们也会不断的对分支进行评估,做适当的剪枝——因此当我们找到问题的解之后,一来思维的漫长繁杂的过程已经在大脑里面淡化得差不多了,只有那些引向最终结论的过程会被加“高亮”——我们在思考的过程中本就会不断的抛弃无效的思路,只留下最有希望的思路。简而言之就是最后证明没用或者早先我们就不抱希望的一些想法就被从工作记忆中扔掉了。二来,思考过程是我们的空气和水,而“《像外行一样思考,像专家一样实践》中说写论文应该写得像侦探小说一样,我很赞同。欧几里德式的介绍,除了提供枯燥的知识之外,并没有提供帮助人获得知识的东西——思维(关于对数学书籍的欧几里德式写法的批评其实也是由来已久了,并且有人呼吁了好几种其它的教学方法)。从这方面,我们所尊敬的一些“圣经”级书籍在传道授业上还不如侦探小说,前者是罗列一大堆知识,后者则是阐述获得知识的过程——推理&联想。
既然如此,也就难怪古往今来算法牛人们算法牛,但却没有几个能真正在讲述的时候还原自己的思维过程的(那个“ 渔”字),手把手的教学生走一遍推理的思路,就可以让学生获得思维过程的训练。金出武雄在然而,我们都是人,人类该有的思维形式,我们难道不是都有吗。既然如此,思维本身又有什么需要一遍遍教的呢?