<audio id="audio" title="74 | 程序员练级攻略：理论学科" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ce/8e/ce478a62a9c0ea27e629c615a444068e.mp3"></audio>

进入专业的编程领域，算法、数据结构、网络模型、计算机原理等这样的计算机科学专业需要学习的理论知识是必须要学习的。下面我们先来看看数据结构和算法。

# 数据结构和算法

算法是比较难学习的，而且学习“算法”是需要智商的。数组、链表、哈希表、二叉树、排序算法等一些基础知识，对大多数人来说是没什么问题的。但是一旦进入到路径规划、背包问题、字符串匹配、动态规划、递归遍历等一些比较复杂的问题上，就会让很多人跟不上了，不但跟不上，而且还会非常痛苦。是的，解决算法问题的确是可以区分人类智商的一个比较好的方式，这也是为什么好些公司用算法题当面试题来找到智商比较高的程序员。

然而，在很多时候，我们在工作中却发现根本用不到算法，或是一些基本的算法也没有必要实现，只需要使用一下第三方的库就好了。于是，导致社会上出现很多“算法无用论”的声音。

对此，我想说，算法真的很重要。我这20年的经历告诉我，无论是做业务还是做底层系统，经常需要使用算法处理各种各样的问题。比如，业务上我需要用算法比较两个数组中差异的布隆过滤器，或是在做监控系统时实时计算过去一分钟的P99统计时的蓄水池算法，或是数据库的B+树索引，还有Linux内核中的epoll的红黑树，还有在做服务调度里的“背包问题”等都会用算法，真的是会本质上帮助到你，也是会让你瞬间会产生成就感的事情。

虽然算法很难，需要智商，但我还是想鼓励你，这其中是有很多的套路是可以学习的，一旦学会这些套路，你会受益无穷的。

这里有几本书着重推荐一下。

<li>
**基础知识**。《[算法](https://book.douban.com/subject/10432347/)》，是算法领域经典的参考书，不但全面介绍了关于算法和数据结构的必备知识，还给出了每位程序员应知应会的50个算法，并提供了实际代码。最不错的是，其深入浅出的算法介绍，让一些比较难的算法也变得容易理解，尤其是书中对红黑树的讲解非常精彩。其中，还有大量的图解，详尽的代码和讲解，也许是最好的数据结构入门图书。不好的是不深，缺乏进一步的算法设计内容，甚至连动态规划都未提及。另外，如果你觉得算法书比较枯燥的话，你可以看看这本有趣的《[算法图解](https://book.douban.com/subject/26979890/)》。
</li>
<li>
**理论加持**。如果说上面这本书偏于实践和工程，而你看完后，对算法和数据结构的兴趣更浓了，那么你可以再看看另一本也是很经典的偏于理论方面的书——《[算法导论](https://book.douban.com/subject/20432061/)》。虽然其中的一些理论知识在《算法》那本书中也有提过，但《算法导论》这本书更为专业一些，是美国计算机科学本科生的教科书。
</li>
<li>
**思维改善**。还有一本叫《[编程珠玑](https://book.douban.com/subject/3227098/)》的书，写这本书的人是世界著名计算机科学家乔恩·本特利（Jon Bentley），被誉为影响算法发展的十位大师之一。你可能不认识这个人，但是你知道他的学生有多厉害吗？我例举几个，一个是Tcl语言设计者约翰·奥斯德奥特（John Ousterhout），另一个是Java语言设计者詹姆斯·高斯林（James Gosling），还有一个是《算法导论》作者之一查尔斯·雷斯尔森（Charles Leiserson），还有好多好多。这本书也是很经典的算法书，其中都是一些非常实际的问题，并以其独有的洞察力和创造力，来引导读者理解并学会解决这些问题的方法，也是一本可以改善你思维方式的书。
</li>

然后，你需要去做一些题来训练一下自己的算法能力，这里就要推荐 [LeetCode](https://leetcode.com/) 这个网站了。它是一个很不错的做算法训练的地方。现在也越做越好了。基本上来说，这里会有两类题。

<li>
**基础算法题**。其中有大量的算法题，解这些题都是有套路的，不是用递归（深度优先DFS、广度优先BFS），就是要用动态规划（Dynamic Programming），或是折半查找（Binary Search），或是回溯（Back tracing），或是分治法（Divide and Conquer），还有大量的对树、数组、链表、字符串和hash表的操作。通过做这些题能让你对这些最基础的算法的思路有非常扎实的了解和训练。对我而言，Dynamic Programming是我的短板，尤其是一些比较复杂的问题，在推导递推公式上总是有思维的缺陷（数学是我的硬伤）。做了这些题后，我能感到我在动态编程的思路上受到了很大的启发。
</li>
<li>
**编程题**。比如：atoi、strstr、add two nums、括号匹配、字符串乘法、通配符匹配、文件路径简化、Text Justification、反转单词等，这些题的Edge Case和Corner Case有很多。这些题需要你想清楚了再干，只要你稍有疏忽，就会有几个case让你痛不欲生，而且一不小心就会让你的代码写得又臭又长，无法阅读。通过做这些题，可以非常好地训练你对各种情况的考虑，以及你对程序代码组织的掌控（其实就是其中的状态变量）。
</li>

我觉得每个程序员都应该花时间和精力做这些题，因为你会从这些题中得到很大的收益。我在Leetcode上做的一些题的代码在这——我的 [GitHub](https://github.com/haoel/leetcode) 上，可以给你一些参考。

如果能够把这些算法能力都掌握了，那么你就有很大的概率可以很容易地通过这世界上最优的公司的面试，比如：Google、Amazon、Facebook之类的公司。对你来说，如果能够进入到这些公司里工作，那么你未来的想像空间也会大很多。

最后，我们要知道这个世界上的数据结构和算法有很多，下面给出了两个网站。

- **[List of Algorithms](https://www.wikiwand.com/en/List_of_algorithms)** ，这个网站罗列了非常多的算法，完全可以当成一个算法字典，或是用来开阔眼界。
- 还有一个数据结构动画图的网站 [Data Structure Visualizations](https://www.cs.usfca.edu/~galles/visualization/Algorithms.html)。

# 其它理论基础知识

下面这些书，基本上是计算机科学系的大学教材。如果你想有科班出身的理论基础，那么这些书是必读的。当然，这些理论基础知识比较枯燥，但我觉得如果你想成为专业的程序员，那么应该要找时间读一下。

<li>
《[数据结构与算法分析](https://book.douban.com/subject/1139426/)》，这本书曾被评为20世纪顶尖的30部计算机著作之一，作者Mark Allen Weiss在数据结构和算法分析方面卓有建树，他在数据结构和算法分析等方面的著作尤其畅销，并广受好评，已被世界500余所大学用作教材。
</li>
<li>
《[数据库系统概念](https://book.douban.com/subject/1929984/)》，它是数据库系统方面的经典教材之一。国际上许多著名大学包括斯坦福大学、耶鲁大学、德克萨斯大学、康奈尔大学、伊利诺伊大学、印度理工学院等都采用本书作为教科书。这本书全面介绍了数据库系统的各种知识，透彻阐释数据库管理的基本概念。不仅讨论了数据库查询语言、模式设计、数据仓库、数据库应用开发、基于对象的数据库和XML、数据存储和查询、事务管理、数据挖掘与信息检索以及数据库系统体系结构等方面的内容，而且对性能评测标准、性能调整、标准化以及空间与地理数据、事务处理监控等高级应用主题进行了广泛讨论。
</li>
<li>
《[现代操作系统](https://book.douban.com/subject/3852290/)》，这本书是操作系统领域的经典之作，书中集中讨论了操作系统的基本原理，包括进程、线程、存储管理、文件系统、输入/输出、死锁等，同时还包含了有关计算机安全、多媒体操作系统、掌上计算机操作系统、微内核、多核处理机上的虚拟机以及操作系统设计等方面的内容。
</li>
<li>
《[计算机网络](https://book.douban.com/subject/1391207/)》，这本书采用了独创的自顶向下方法，即从应用层开始沿协议栈向下讲解计算机网络的基本原理，强调应用层范例和应用编程接口，内容深入浅出，注重教学方法，理论与实践相结合。新版中还增加了无线和移动网络一章，并扩充了对等网络、BGP、MPLS、网络安全、广播选路和因特网编址及转发方面的材料。是一本不可多得的教科书。
</li>
<li>
《[计算机程序的构造和解释](https://book.douban.com/subject/1148282/)》，这本书也很经典，是MIT的计算机科学系的教材。这本书中主要证实了很多程序是怎么构造出来的，以及程序的本质是什么。整本书主要是使用Scheme/Lisp语言，从数据抽象、过程抽象、迭代、高阶函数等编程和控制系统复杂性的思想，到数据结构和算法，到编译器/解释器、编程语言设计。
</li>
<li>
《[编译原理](https://book.douban.com/subject/3296317/)》，这本书又叫&quot;龙书&quot;，其全面、深入地探讨了编译器设计方面的重要主题，包括词法分析、语法分析、语法制导定义和语法制导翻译、运行时刻环境、目标代码生成、代码优化技术、并行性检测以及过程间分析技术，并在相关章节中给出大量的实例。与上一版相比，本书进行了全面的修订，涵盖了编译器开发方面的最新进展。每章中都提供了大量的系统及参考文献。
</li>

# 小结

好了，最后我们来总结一些今天分享的内容。在这篇文章中，我建议想进入专业编程领域的人，一定要学习算法、数据结构、网络模型、计算机原理等理论知识，并推荐了相应的学习素材，给出了我的思考和建议。

我认为，虽然这些理论知识枯燥难学，而且通常学完了在工作中也并不是马上就能用上，但这些知识是必须要学好的。**这些理论知识可以说是计算机科学这门学科最精华的知识了，认真学习，理解其背后的逻辑和思维方式，会让你受益匪浅**。不管是未来你是要学习新技能，还是解决什么疑难问题，都能在这些知识中获得灵感或者启发。

下篇文章中，我们将分享每个程序员都需要掌握的系统知识。敬请期待。

下面是《程序员练级攻略》系列文章的目录。

- [开篇词](https://time.geekbang.org/column/article/8136)
<li>入门篇
<ul>
- [零基础启蒙](https://time.geekbang.org/column/article/8216)
- [正式入门](https://time.geekbang.org/column/article/8217)

- [程序员修养](https://time.geekbang.org/column/article/8700)

- [编程语言](https://time.geekbang.org/column/article/8701)
- [理论学科](https://time.geekbang.org/column/article/8887)
- [系统知识](https://time.geekbang.org/column/article/8888)

- [软件设计](https://time.geekbang.org/column/article/9369)

- [Linux系统、内存和网络（系统底层知识）](https://time.geekbang.org/column/article/9759)
- [异步I/O模型和Lock-Free编程（系统底层知识）](https://time.geekbang.org/column/article/9851)
- [Java底层知识](https://time.geekbang.org/column/article/10216)
- [数据库](https://time.geekbang.org/column/article/10301)
- [分布式架构入门（分布式架构）](https://time.geekbang.org/column/article/10603)
- [分布式架构经典图书和论文（分布式架构）](https://time.geekbang.org/column/article/10604)
- [分布式架构工程设计(分布式架构)](https://time.geekbang.org/column/article/11232)
- [微服务](https://time.geekbang.org/column/article/11116)
- [容器化和自动化运维](https://time.geekbang.org/column/article/11665)
- [机器学习和人工智能](https://time.geekbang.org/column/article/11669)
- [前端基础和底层原理（前端方向）](https://time.geekbang.org/column/article/12271)
- [前端性能优化和框架（前端方向）](https://time.geekbang.org/column/article/12389)
- [UI/UX设计（前端方向）](https://time.geekbang.org/column/article/12486)
- [技术资源集散地](https://time.geekbang.org/column/article/12561)


