如何学好算法和数据结构之我见

时间:2020-12-26 10:21:33
  • 算法到底是什么?

非形式地说,算法是为实现某个任务而构造的简单指令集。以日常用语来说,算法又称为 过程或者方法。算法在数学中也起着非常重要的作用。古代数学文献中就包含有执行各种各样计算任务的算法描述。例如,我国古代数学经典《九章算术》中就记述 了包括求最大公约数、最小公倍数、开平方根、开立方根等在内的诸多算法。现代计算机科学中更是充满了各种各样的算法。例如,求解最短路径的狄克斯特拉算法,进行字符串匹配的KMP算法等等。 虽然算法在数学中已有 很长的历史,但在20世纪之前,算法概念本身一直没有精确的定义。1900 年,德国数学家希尔伯特在巴黎举行的世界数学家大会上发表了至今仍著名的演说。在演说中,他提出了 23 个数学问题,并认为它们是对下一个世纪的挑战。其中的第 10 题就是关于算法的。 希尔伯特的第10个问题是要设计一个算法来测试多项式是否有整数根。他没有使用算法这个术语,而是采用了下面这种表述:“通过有限多次运算就可以决定的过程”。有意思的是,从希尔伯特对这个问题的陈述中可以看出,他明确地要求设计一个算法。因此,他显然是假设这样的算法是存在的,人们所要做的只是找到它。现在我们知道,这个任务是无法完成的,即它是算法上不可解的。但对那个时期的数学家来说,以他们对算法的直观认识,得出这样的结论是不可能的。要想破解希尔伯特的第10个问题,人们不得不等待算法之精确定义的出现。 在丘奇和图灵于 1936 年写的文章中,这样的定义终于出现了。丘奇使用称为 λ 演算的记号系统来定义算法。图灵使用机器来做同样的事情(所以现在我们也常说精确定义上的算法等价于图灵机)。这两个定义后来证明是等价的。算法的非形式概念和精确定义之间的这个联系,从此被称为丘奇-图灵论题。丘奇-图灵论题提出的算法定义是解决希尔伯特第 10 个问题所必需的。1970 年,马提亚塞维齐在戴维斯、普特纳姆和罗宾逊等人工作的基础上,最终证明检查多项式是否有整数根的算法是不存在的。

  • 算法与数据结构之间有着什么样的关系?

正如你所看到的那样,市面上那些讨论相关问题的书籍之取名也都大同小异,例如“数据结构与算法”或者“数据结构与问题求解”,注意根据上一个问题的解答,你应该可以知道所谓问题求解,本质上就是在讨论算法问题。即使那本名叫“算法导论”的经典书籍,里面仍然有很大篇幅在介绍二叉树、红黑树、堆等数据结构。可见,算法与数据结构,二者是相辅相成,密不可分的。如果试图将它们割裂来看,例如讨论算法而不讲数据结构,或者只学习数据结构而对算法只字不提,都是不可能的。一方面,算法一定要借助相应的数据结构才能得以实现。例如堆排序算法就必须基于堆这种数据结构来实现。另一方面我们在定义一个数据结构的同时其实也已经定义了与之相关的操作。这些操作本身执行的步骤就是算法。例如,在介绍树的遍历操作时,就不得不提到深度优先算法和广度优先算法。所以,算法和数据结构之间早已彼此渗入到骨子里,难舍难分了。

  • 掌握算法与数据结构的相关知识对于一个IT从业人员有什么意义?

如果你是一个计算机相关专业的学生,那么数据结构将是你的必修课。如果你要报考相关专业的研究生,那么数据结构又可能位列你的专业课考察范围之内。如果你毕业了准备找工作,那么在很多IT公司的笔试面试题了,算法与数据结构又将成为重要的考点。著名的LeetCode网站上搜集了世界主要大IT公司的笔试面试题数百道,几乎道道都是在考察算法与数据结构的。由此,便不难看出算法的重要性。 无论你是信息技术的从业人员,还是计算机专业的在校学生,再或者是从事相关专业的研究人员,熟练掌握一门计算机语言都重要性都不言而喻。但是不是掌握了这其 中的语法规则就能写出漂亮的程序了呢?答案当然是否定的。因为你还需要另外一样至少同等重要的工具——算法。算法和语言的关系,其实很像是“道”和“术” 的关系。掌握一门语言,就如同习得一门技艺,可以成为一名工匠。但要想从工匠一跃成为大师,单单停留在“术”的层面显然不够,更重要的是悟“道”。而算法无疑就是计算机程序设计中的“道”。

  • 数据结构在现代信息产业中有哪些应用?

有的人可能会觉得数据结构仅仅存在于大学的课本上,而在现代计算机应用中并不常见。一种看法可能是因为大部分语言都提供了封装好的组件来支持结构化数据类型,例如C++中的STL。所以开发人员在编程的时候面向的往往是一些类或者包,而不再是栈或者队列这种基本数据结构。然而,事实上如果你觉得这就已经是数据结构在现代计算机技术中的全部应用,你就大错特错了。很多高级算法或者应用中仍然需要数据结构(也包括一些高级数据结构)。例如机器学习中使用的决策树,显然就是以树这种基本数据结构来实现的。还有kNN算法中则用到了KD树这样的一般很少出现在数据结构教程中的高级数据结构。在现代大规模空间数据库算法中,高级数据结构更是扮演着非常重要的角色。

  • 学习算法之前需要掌握哪些知识,是否会涉及很多数学?

算法和数据结构知识的学习并不需要太多数学知识。在大学计算机课程安排中,往往将离散数学作为数据结构的前置课程。而且离散数学在历史上最初的名字其实就是叫离散数据结构。但是,实际上,即使你没学过离散数学而直接学习算法和数据结构,也完全不会有问题。 但是,在学习算法和数据结构之前,你必须牢固掌握至少一门计算机语言。JAVA、C、C++或者Python都无所谓,但是你至少应该会其中一门。因为算法和数据结构都是面向应用的学问,在学习过程中涉及很多编程实践方面的内容。所以掌握一门计算机语言就势必成为你学好算法与数据结构知识的必备要素。

  • 如何学好算法和数据结构?

首先, 我这里的所谓“学好”,标准就是你能够用数据结构和算法知识来编程解决实际问题。比如自己能够在没有任何资料的帮助下编程解决8皇后问题。这其中就涉及到两个能力了。数据结构和算法知识肯定是一方面啊,另一方面呢?编程啊! 语言必须得学好,不管是C还是C++还是Java,什么都行,至少得先掌握其中一门。你可能会感到吃力和心虚的地方在于,自己好像也学过一门计算机语言,但是在写程序的时候总感觉束手无策、力不从心。那正好用数据结构和算法课程来深化你的编程能力。事实上,算法与数据结构同编程本身就是相辅相成的,如果有主次,那么你至少得先掌握一门语言,但也不必十分精通。因为在此基础上去学习数据结构和算法,将会反作用于你的语言能力本身。最终两种能力将同时获得提升。 其次,看书,看一本好书,认认真真的看一本好书,从头到尾认认真真的看一本好书。这样做的目的在于让你在最初学习的时候,建立一套完整的、系统性的框架和认识。 最后,现在你语言已经过关了,手头还有一本好书,然后呢?当然是得编程实践了。看到书上的一些实际问题:比如约瑟夫环问题,比如舞伴问题,那就自己编程解决吧(前提是理论已经确实懂了,不要坐在电脑前面眼前一片漆黑,然后想着程序该怎么编呢?那只能说明你书还没看懂。)

“数据结构与算法”(有时也称数据结构)课程是大学计算机专业的重要基础课程。考研中,数据结构也几乎是专业课之必考。另外,在实际工作中,数据结构依然很有用。至少很多公司面试笔试也会考的。可以坦白地讲,如果你数据结构知识为零,那基本上你是无法从事“更有质量”的开发工作的。尽管数据结构非常重要,但这门课由于逻辑性要求较强,非常抽象,因此很多学生面对它都显得力不从心。那么到底该如何学好数据结构呢?我想这才是同学们最关心的问题吧。至于什么心态上的、方法论上的问题我们这里就不浪费笔墨了。我们重点来讲点实际的。


首先,一般的规律是你至少得掌握一门计算机语言之后再来学习数据结构。高校中课程一般也是这么排的。如果你语言学得不好,然后就直接学数据结构,那么你的理论就无法落地,就无法得到深化,也没有办法应用。特别注意,我这里的所谓“学好”,标准就是你能够用数据结构和算法知识来编程解决实际问题。比如:最起码自己能够在没有任何资料的帮助下编程解决8皇后问题吧。这其中就涉及到两个能力了。数据结构和算法知识肯定是一方面啊,另一方面呢?编程啊!你连编程都是半瓶子醋,就算数据结构学到天上了又怎么能解决问题呢?纸上谈兵吗?首先语言必须得学好,不管是C还是C++还是Java,什么都行,但得有一个精的,然后再来玩数据结构。如果语言不过关,那就再修修语言吧,啥时候语言通了再来讲数据结构。

其次,看书,看一本好书,认认真真的看一本好书,从头到尾认认真真的看一本好书。简单的说,你如果要想把这个东西(数据结构与算法)学好,自己备一本(至少一本)专门讲这个东西的书肯定是必须的。我很难想象出如果你想把这个东西学好,然后又不用看书的方法...工欲善其事,不先利其器。一本好的书能够让你学得更轻松,能够让你理解更深刻,让你学得更系统。有的人会说,网络这么大,我就上网找资料学,问题上网上的东西,例如帖子或电子文稿,都非常不系统。就好像你中学学物理,只学了力学和热学,却没学电磁学,就算你力学学得再好,你能去参加高考吗?所以如果是个一瓶子不满半瓶子晃的水平,那根本就不能说自己学了或者学会了,这都言之过早啦。所以要是缺了一本正经八百的书,那在此之后所有的意见和学习方法都是无从谈起了。如果你现在手头还没有一本讲数据结构和算法的书,那我觉得我这篇文章,你基本上也甭看了,看完了还是啥也不会。

当然,也有很多人会说到让我推荐一些这方面的书籍。毕竟,讲数据结构和算法的书太多了,真是太多了,不过好的不多啊,呵呵。的确,书是很多的,而且其中有些书很经典,但是我奉劝同学们不要太好高骛远,还是脚踏实地点好,俗话说:万丈高楼平地起啊。一些特别经典的东西理解起来偏难,例如:Knuth的那套《计算机程序设计艺术》(现在分卷分册的中英文对照版国内已经都出了),该书绝对是这么学问的权威之作,以及《算法导论》(大名鼎鼎啊),这两部书都很经典,但刚开始可能不太适合大家。事实上,《计算机程序设计艺术》是非常晦涩的,绝对不适合作为学习算法的教材来使用。《算法导论》是美国很多大学采用的经典教材,可读性较强,但仍然需要有一定基础,因此并不太适合初学者。


比较适合初学者的书籍,我建议大家可以看看我编写的《算法之美——隐匿在数据结构背后的原理(C++版)》。我一直以来都认为用面向对象语言来讲解数据结构非常合适。因为面向对象的“抽象性”、“封装性”等特点用来编写“结构”,从思想上更容易被接受,也更容易讲得通,对于初学者来说,困难也就会小很多。我这本书除了采用C++作为描述语言以外,讲得还算通俗易懂吧,对于那些复杂的算法用了很大的篇幅去描述算法的过程,而且图特别多,一本书下来有大概400多张图表,我觉得这样更容易帮助读者理解。另外一个特点是,这书里面的代码都是绝对可以运行的,绝非伪代码,这里面结合具体的问题和一些经典实例都配有完整的代码。我觉得这样能够让读者提供实际的解决问题的编码能力。另外书中的例子取材都非常好,是一些经常被提到的经典问题,这些示例程序无论是对于你的理解,还是对于你的实践都大有裨益。


探秘算法世界,求索数据结构之道;汇集经典问题,畅享编程技法之趣;点拨求职热点,敲开业界名企之门。


如何学好算法和数据结构之我见

《算法之美——隐匿在数据结构背后的原理》,如果你是该书的读者,强烈建议你加入算法学习群(495573865),内有更多资源等你,而你在读书中遇到的疑问也将得到我第一时间的解答。更多关注本博客,我将陆续发布该书全部源代码至本博客。