华山论剑:算法

来源:互联网 发布:ddos攻击软件下载 编辑:程序博客网 时间:2024/04/28 08:49

这其实是CSDN里一个帖子:

http://topic.csdn.net/u/20071126/15/8A29AA79-6705-47D7-A16F-8EC226D04172.html


讨论算法的,里面2位大师(至少我认为是)讨论颇为精彩,整理于此处,希望更多人多可以看看。

 

-------------------------------------------------------------------------------------------------------------------------------------------

 

zhenming_liu:


不好意思又提出了这样一个可以有口水战的问题。很多人的答案是“有用”,大部分的理由是不懂算法就会限制“思维”。我觉得这种答案有点牵强。软件产业现在也是有蛮细的分工的。一个人精力多花在了算法之上,那他就少了精力放在更高层面的设计问题上。就好像读设计的大部分是不会碰到土木用的力学。我们能不能说算法就是土木工程师的活,而酸法以外的架构和设计则是设计师的活呢?对设计师而言,懂力学自然是好,但是即使不怎么懂,也会无伤大雅。

所以我觉得学了算法当然有用,但是学算法花的时间会不会不值得。当然我说的学算法是在看完introduction to algorithm大半本以后的学习---intro to algo是蛮基本的, 但是像The arts of computer programming或者concrete mathematics就有点过头了。

即便在现实生活中,很多情况下我们都不会碰到有难度的算法。如果碰到有难度的算法,整个开发团队只要有一个人有本事解决,问题就不算是问题了。

所以我蛮想知道这两件事的,
1. 在这个论坛的,究竟有多少人是每天工作要碰到算法的?具体而言是哪些算法(离散的,信号处理的或者图形的?)如果你需要设计算法,有多少时候是找开源代码能解决问题的?有多少时候要自己真正设计的?
2. 究竟有多少人读过"the art of computer programming"?我自己算是大概翻过了这本书,很多章节我都从其他地方看过类似的材料。但是我不觉得直接看teh arts of computer programming是学习那些课题的高效方式。

 

Vitin:


其实学习算法有两个好处:直接的和间接的.
直接的好处就是将学到的算法使用在工作中.而间接的,就没有定论了,我觉得是能够提升思维能力.
这两个好处中,我觉得提升思维能力更重要.说到底算法还是比较基础的东西.而越基础的东西,越是难以直观地评价它的价值.但是,正是由于它是基础的,其投资回报率其实更高.比如LZ所说的高层设计,也会因思维能力的提升而获益.另外,就算法本身而言,我觉得学习算法的主要目的是具备设计新算法的能力,而不是使用已有的算法.因为,人们很难预测将来的需求,只为现有需求付出努力回报率是不高的.因此学习算法的重要好处是:能够为将来未知的需求作好准备.
总之,我的体会是:算法的实际价值总是比我们所估计地要高得多.

当然,也没有必要因此就非算法不行.总体而言,它和其他基础的东西一样,是高投入高回报率的科目,但是并不是所有人都必须投入它.是否要花精力学习它,要学到什么程度,对每个人来说答案都是不同的.就象LZ所说,工作中直接遇到算法难题的情况平均而言是不多的.所以,也不必被算法的美好前景所诱惑.最好是根据自己的目标和实际情况,做最优选择.而一旦选择的学习算法,就必须下定决心做巨大的付出.

就我个人而言,工作中是经常要碰到算法的;但是遇到难题的情况很少,大多数情况下,具备普通的能力就可以了.
目前,我正在学习TAOCP,学习的主要目的是提高算法设计能力(而不是应付现有的工作).但是,我发现自己的数学基础还是有些薄弱(基础以前没打好,后悔啊),所以现在正在看Concrete Mathematics.(欢迎与我讨论这两本书上的内容,呵呵)

 

 

zhenming_liu:


To Vitin,

TAOCP我是很不建议看的。厚厚的三本书你觉得两年能看完吗?两年不看这本书你能看很多别的书。再说作者出书的本意是写本关于编译器的书,所以一则用了很难懂的汇编语言,二则是太过注重信息细节的处理。现在算法的意义跟Knuth甚至Dijkstra的那个年代是有很大不同的。 首先我们出离了微观下的代码编写(不会以写段一两行代码作目的。TAOCP成书后几年的network flow和其他图论算法的出现,已经令算法的style已经跟Knuth所说的很不同了。如果你看看Kleinberg的搜索算法或者Google的page rank, "style"就跟Knuth完全不同了。Knuth出书的时候,Cook-Levin Theorem没出现(就是SAT-3是NP-Complete的定理), randomized algorithm的出现也是好年以后的事。现代意义上的hash function也是遥遥无期;更不要说approximation algorithm, online algorithm, hardness of approximation这些概念了。

所以introduction to algorithm以后,你可以试一下Kleinberg的algorithms, 如果你还想看,可以试一下专门的领域, 这里列出了一点书单 
随机算法:"randomized algorithms", "probability and computing"
在线算法: "online computation and competative analysis"
近似算法:"approximation algorithms"。

但是,看完这些书以后,我还是觉得算法挺没用的。

 

Vitin:

 

呵呵,LZ的问题很直白.

不过我不能同意"算法与数据结构究竟有多大用"和"现在在工业界究竟有多少人会碰到算法,而且都是些什么算法"之间有等价关系.原因之前已经说了.所以,LZ的后一个问题我就不回答了.

关于TAOCP,还是要解释一下的.这部书之所以非常有名,不是因为它覆盖了所有的算法,也不是仅仅因为它很有难度;而是因为它系统地、严谨地、深刻地分析了许多最基本的算法,它的理论体系构成了现代程序设计的基础.


是的,如果说算法是编程的基础的话,那么TAOCP就是算法的基础.我相信,很少有在算法界取得成绩的人没有看过这本书.比如在introduction to algorithm 中就多次引用了Knuth和他的TAOCP.当你看的算法书的作者们也都在看TAOCP时,你是否觉得没必要看它呢?


TAOCP中的算法是以一门汇编语言写的,那时因为Knuth认为如果编程人员只需要学一门语言的话,那他应该学一门汇编语言.毕竟,汇编是最接近计算机本质的语言.所以,Knuth用汇编语言做载体,主要希望通过这种方式来引导读者熟悉计算机的本质.Knuth的MIX汇编语言,是和TAOCP第一版所处的时代非常匹配的.诚然,现代的汇编语言已经和当时有很大不同;但是,如果能从计算机历史的源头处开始学习,不是更能把握其本质吗?我觉得TAOCP的主体思想就是究根问底,把握本质.所以,学习最初的MIX仍然是有益的.另一方面,为了加入第一版之后几十年的成果,Knuth在他的第四版中设计了一门新的汇编语言--MMIX,它是现代化的MIX.此外,即使不去学习MIX或MMIX,也可以通过TAOCP学习算法.因为算法本身是超越语言的.我一般用C++来写这些算法,并没有任何不适合的地方.(题外话:B.S.的TC++PL也同样参考了TAOCP,这令我更加确信TAOCP的重要性).


TAOCP的定位就是基本的算法书,所以它并不关注(或偏向)某个应用领域,也不关注某个style.(是不是本意为了编译器呢?这无关紧要了,因为它的实际内容决定了它的读者已经远远超过编译器的作者了.强调一点:Knuth选择汇编,理由是我之前说的,而不是为了编译器;至于TAOCP未出版的部分涉及编译器和计算机语言,也是因为它们和排序查找、随机数生成等等一样,属于基础和本质的东西,而非相反).所以,任何使用算法者,都能从中获益.TAOCP不是算法的终结,而是开始.你需要做的,是通过学习它,而学会自己设计算法、分析算法;而不是仅仅让它给你提供一个现成的答案.TAOCP提供了许多算法,仅仅因为它们最基础,也最适合作为教授算法的素材.如果取其形而去其神,就大大模糊了TAOCP与其他算法书的区别了.所以,我更加认为,通读一遍TAOCP是非常有用的.如果你认为其他算法书对你没有用处,你更应该读一遍TAOCP.

当然,这并不是说必须学习TAOCP,我只是想清楚地阐明TAOCP的价值,以免低估.当然代价是巨大的."需要多少时间"要看个人的实际情况了.即使每天都有8个小时学习,我估计也不是象其他书那样几天或几周就可以完成的.因此,两年是一个很正常的数字.我不想说其他书怎样怎样.总之这是一个机会成本的问题,我相信每个人都有自己的选择;我也相信即使选择的各不相同,也没有对错之分.最重要的是根据你的目的做出选择;并且,如果决定了,就不要轻易放弃.

 

zhenming_liu:

 

To Vitin,
呵呵我算是跟Knuth有一点师承。我本科的导师是他的第二代学生。我怎么敢对他有任何不敬。不过我自己觉得TAOCP从来没有被低估,而是被(国)人过高的评价了,现在已经变得有点像圣经了,就是大家都推荐看,大家都不看的一套书。我上面说的style可能有点误导(让人联想到编程风格)。我觉得用fashion应该更恰当一点。你真的要看看我说的那些书去感觉一下区别。

退一步说,你见过哪所大学真的用TAOCP作教材吗?这是不是侧面的说明了它不适合去做教材/学习读物?

Knuth出书的原因,我记得是看到两三年前一份报纸对他的专访中看到的。你如果再看看Vol 4, 5, 6的draft(我不太清楚已经出了没有),你会看到所有书的背后隐隐约约的想写个编译器。

你也提到了B.S, 我想问一个问题,你觉得B.S.又懂多少算法?他的C++的成功,也不是因为算法的原因。

你有两个观点我不怎么同意,1. 学习要不要从源头学起。你记得你学微积分的时候,有拿起牛顿的principle来读吗?所以同样的,我觉得后人归纳总结后的书看起来是会更有效率的。2. 算法的有用和对思维的陶冶。我首先应该道歉,我不应该很武断的说“没用”。但是不是所有有用的东西你都需要去学。我也可以肯定你学纯粹数学和理论物理,也会很陶冶思维,甚至也会对写程序有用。但是这样子的有用,我觉得是费大力作小功;而且是也不明确自己的目的的表现。

你如果很喜欢TAOCP和Knuth那个领域,你可以去选择做个这方面的专家或者业余爱好者。但是我觉得TAOCP对你在工业界的发展,或者对国内软件的发展,没有什么大的帮助。

TAOCP的问题,你愿意的话,我可以再跟你线下谈。我这个帖子最感兴趣的还是究竟有多少人真的在工作中用“算法”。

 

Vitin:

 

To zhenming_liu:
   
很高兴看到你认真地回答每一个人的发言,谢谢.
观点不同没有关系.一方面这可以促进我们交流;另一方面任何观点都是有局限的,也许是它们成立的充分必要条件不同而已.所以我和乐意和你交流,从而让彼此的视野更宽广,见解更全面.
   
当然LZ希望在这个帖子里关注另一个问题,所以关于TAOCP的讨论就不深入下去了.
这里仅就你所提到的说一下我的见解,作为结束.其他可以线下谈,呵呵.

关于教材的问题,TAOCP确实不适合做为大学教材,我觉得部分原因是它的难度(可能不适合所有大学生,或所有处于大学阶段的人),部分原因是它的内容(作为一门课而言)太多.不过它的一部分确实有作为教材的先例. "1.2节数学基础"曾经作为教材被使用(一开始是由Knuth亲自授课),此后演变为"具体数学" 这本书.我的观点是:TAOCP在大学阶段作为课外学习是很好的,我也后悔当时自己没有做到这一天.

关于Knuth出书的原因,之前我也说了,更重要的是书的实际意义.我也知道他的后续章节有关于语言和编译器的.我的理解是它们正是编程中最本质的东西;以及以此为出发点最适合学习算法.

关于B.S.的算法功底问题.我觉得一个人能够取得成绩,是和他整体的知识和能力有关的.成功往往很难复制,一个原因正是夸大了直接原因而忽略的作为背景和底蕴的东西.不说这些形而上的,单就C++而言,如果B.S.想到要发明C++是灵光一现的结果,那么他将C++设计并实现出来与其深厚的算法功底是分不开的.要知道,算法功底并不只是能设计出某个算法,解决了某个具体问题而已.设计一门语言语言不可能不需要算法.B.S.关注于C++语言的设计和演化,是因为他既有这个愿望,也有这个能力.同时,就象不能将算法看得太简单,也不能将设计一门语言看得太简单.(B.S.没能发明什么算法?他发明了一门语言!)有多少人能够精通算法,又有多少人能够设计出一门语言?所以,不能低估啊.

关于从源头学起的问题.我不是说必须,我是说可以,并且有益.必须的反义是不是必须不,而是不必须.所以怎么学习是个人的事,而TAOCP推荐了一种学习方法,并且它是有效的.

关于算法的价值问题,之前已经解释过了,只是和LZ观点不同而已.重复一下,我认为自己是对的,但不认为LZ是错的.在合适的条件下做合适的选择,以及如何看待自己的目的,并采取什么行动,每个人可以有自己的见解.

最后说一下TAOCP被神化的问题.我相信,不管是高估还是低估,都是没有获得充分信息的结果.我也相信,那些说TAOCP如何如何神奇的人中有很多还没有读过它.我想,最有资格评论它的价值的是那些读过的人.所以,我觉得,还是读一下比较好.我相信,当有很多人读过以后,它就不会再被神化;同样的,就会有更多的人清楚它的价值.


因此,这个问题,我确实不能回答,因为我还没有读完.我只能给出自己的见解:对我而言,读一遍TAOCP,是值得的.


有时候,你需要冒险;有时候,你会觉得冒险是值得的;有时候,你将发现,你曾经以为冒险的地方其实并没有多大的风险.有些结果是偶然的,有些则是必然的;重要的是有决心,并且能为自己的决定负责.

 

zhenming_liu:

 

我是那个忽然欠揍开了这个帖子的楼主。好久没来了。。。。不过发现这样的帖子什么时候都很热闹的。

先八卦一下那个中国余式定理,听项武义那位老先生说过Chinese Remainder theorem是韩信点兵,不是那个《孙子兵法》;不知道有没有人能搞清楚他们的关系。

继续说算法和数学吧。我想我应该澄清,我没有说,“算法不用学”。我只是想说,以我自己的观察看来,算法没有用---至少是对大部分人来说是对的。就好像计算理论中Church Turing Thesis认为不同的计算模型中相同的算法/程序,只会有polynomial time的区别---这些烂thesis怎么都跟软件开发粘不上边了吧,但是懂一点还是会要的。

很多人的思路是,不用算法的人是“软件工人”,“软件工人”只有在懂算法的情况下,才能升级成“软件架构师”。有人拿建筑中的建筑工人与建筑师作类比。我是蛮喜欢这个类比的。因为软件工人的确是入门门槛不高,做着难度比较低的事情。但是一般情况下,升级成“软件架构师”多数情况下不是因为他搞懂了什么push-relabeling的network flow algorithm, 而是他更加会“架构”了。架构方面的发展,应该走的是Gang of Four的design pattern或者Richard Gabriel的pattern language。 这些人的工作也很直接的联系上了建筑行业。譬如design pattern的出处就是Christopher Alexander的"A pattern language". 所以这是我一直最想强调的,算法的作用似乎远远没有比架构重要。

李开复那篇关于算法的文章我也是最近才看过(http://www.yuanma.org/data/2006/0623/article_929.htm)。通篇看完以后,我还是没看出他对算法的研究有多深。他提到最难的是动态规划,剩下的东西看来看去都是象是听个物理系的本科生去扯相对论:“有了相对论就有了原子弹,有了原子弹就要小日本人一点气都没有了。相对论很重要吧?”李老兄的文章来来去去都是这种层面的解释。真的看不出他算法的“造诣”。

我个人来讲,是很不喜欢那种懂算法便是“高人”,不懂算法便是“一般人”的定论。如果这是对的话,那每个人都自然想成为“高人”,而不愿意“低人一等”,便至少要声称很喜欢算法,或者声称很尊敬懂算法的人。这样的定调就提前把让讨论没有意义了。专攻“算法”的人最多只能说他是算法的“专才”。而我私自认为,我们讨论的一个重点,便是这样的专才究竟要有多少?毕竟我觉得,懂得http encoding format, 知道怎么去用Last Modified tag的人,不比懂得streaming algorithm中做aggregation的人次要。

至于数学,我觉得这里的气氛一直都很搞笑(恕我无理)。计算机科学的那些“数学”,很多人都觉得不是真正的“数学”。我们这票人既搞不懂为什么e是transcendental number, 也永远记不住Galois theory, 就我们这种程度,真的不敢说我们懂数学吧-----你即便问清华的姚老爷他懂不懂数学,他多是不肯说他懂数学的。倒是这里的人老是很喜欢吹嘘自己懂数学---至少喜欢读数学。

我的另一个重点是,真的想问,谁在用“算法”?这个方面我是有点偏激的。看到说data mining时可能很有用。的确,我最近也是做了点data mining的东西,懂不懂就3-4G数据进进出出。是需要写点数组和collection以外的数据结构。但是我还是觉得这方面的“算法”,远在TAOCP之下,甚至在Kleinberg之下----反过来说,Kleinberg第一章的randomized stable marriage算法,究竟谁敢用。

我承认贴出了这样的话题不可避免的惹了吵架,以后能不能把问题重点摆在“谁在用算法”?譬如我想听到诸如,路人甲说:“我是个架构师,我关心更多的是商业逻辑。日常工作中没什么机会碰到算法”,路人乙说,“我以前也很专研算法的,因此进入了知命企业xxx, 但是工作了才发现,很少能有机会能露一手,自己设计个算法”,或者其他反面的例子。