购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.4 程序=数据结构+算法

程序员首先要有自己的想法,而写程序只是为了实现自己的想法而已。

而程序员的想法就是用数据结构+算法来描述的。如果程序是一个人,正确的数据结构就像是强壮的体格,高效的算法就像是高尚的性格,而语言,只是一件外衣而已。不同的场景,你会穿不同的外衣,而且外衣可能还有一定的流行趋势,但这些真的不重要。

纠结于语言的程序员,就像是只关注外衣是否漂亮的小姑娘。凡是能够流传千古的作品,你会发现都是不穿衣服的,如图1-10 所示的罗丹的思想者;更有甚者,不仅衣服没有了,就连两个胳膊都是多余的,如维纳斯。

图1-10 就是因为熬夜,我的衣服忘记放哪了

1.4.1 数据结构

数据结构是任何计算机专业的必修课,但是目前有些程序员越来越不重视它。不重视它并不是因为它不重要,而是目前市面上两种主流的面向对象高级语言C++和Java 中,都包含比较完整的基本数据结构的库实现,它们分别是C++中的Standard Template Library(STL)库和Java中的Container类。对用户来说,只要直接拿来使用就可以了。

为了使某种特定的数据结构能够支持所有的数据类型,C++和Java 分别使用了两种泛型技术,分别是C++的模板技术和Java 中面向对象的继承技术,如程序1-1所示。

在Java中,所有的数据类型都继承于Object,同时ArrayList 支持装入任何继承于Object 的数据类型,用一句俗话讲就是:“ArrayList 是一个筐,乱七八糟都可以装。”不过需要注意,从ArrayList 中取出数据的时候需要转换回正确的原始类型,如果没有转换回原始的类型,运行时就会出错,同时转换也有一定的效率损失。

程序1-1 C++和Java 的两种泛型技术

1 /*java实现*/

2 ArrayList List = new ArrayList();

3 List.Add(1);

4 List.Add("string"); /*正确*/

5 /*C++实现*/

6 vector<int> v1;

7 v1.push_back(1);

8 v1.push_back("string"); /*错误*/

C++的模板技术就没有类似的问题。你在声明一个vector对象的时候,必须如程序1-1 中第6行所示,指定它要保存的数据类型为int,以后这个v1只能存入你指定的数据类型int了。对于模板技术,C++的STL无疑是模板技术的杰出代表,目前它已经成为C++语言标准的一部分,可见确实不同凡响。对于STL 有三层境界,第一层为会用STL,大家可以参考《Effective STL》 [6] 。第二层为明白其中的原理,对应的参考书为《STL 源码剖析》 [7] 。借用书中的一段话为:“源码之前,了无秘密”,确实如此。第三层为能扩充STL,这个层次就需要你自己来写本参考书了。

关于泛型技术的模板实现和继承实现,也有很多优劣的争论。吵架这种事通常我都会躲得很远,这次我依然不例外。值得注意的是,新版的Java 也支持模板技术。你需要根据特定的场合来决定使用哪种方法。

有趣的是,当有人在热烈争论模板好还是继承好的时候,还有些工程师却在认真地思考,最终他们写出了这样的C++语句:class String: public Array<char,String>。这种混合使用继承和模板的技术详细的讨论可以参考《ATL Internals》 [8] 的Appendix A。利用模板可以避免继承中动态绑定的效率代价。利用继承可以提供模板技术不能提供的多态行为,这种思想可谓鱼和熊掌兼得。基于这种思想,微软建立了一套用于快速开发组件(COM)的Active Template Library(ATL)。可见,少批评、多借鉴、多思考才是我们对待不同技术的正途。

虽然有了很多优秀的数据结构库实现,但是我们还需要认真学习数据结构的基本知识和思想。现实世界中的问题往往比较复杂,很难用一两种基本的数据结构来模拟和解决,往往需要你综合利用各种基础的数据结构。同时,用户的需求千变万化,千差万别,有的时候需要你构造一个全新的数据结构才行。这些都要求你有扎实的数据结构基础知识。

1.4.2 算法

算法到底是什么?以下是Wikipedia 的定义:an effective method expressed as a finite list of well-defined instructions for calculating a function. In simple words an algorithm is a step-by-step procedure for calculations。如果你不明白也没关系,其实我也不明白。算法本身就没有一个准确的、排它性的定义,正可谓:“道可道,非常道!”

你可以不知道算法的准确定义,但是一定要知道算法很重要。算法是计算机科学的核心,如果没有算法,计算机几乎不配再称为科学。虽然计算机语言和开发平台日新月异,但万变不离其宗的还是那些算法和理论。是否精通算法是菜鸟和老手的区别,也是低薪和高薪的区别。IT领域500强公司面试基本上都是算法题。算法也是区分一般任务和艰巨任务的一个指标。一般任务就是指做一个网站,只会给你3千块钱,是产业链的低端;而艰巨任务就是指解决北京的交通问题,国家会给你10个亿的。但是这种问题,绝对是一个算法密集性问题。

描述算法有两种方法,一种是利用流程图方式,如图1-11所示。

图1-11 算法流程图描述

这个算法是我最钟爱的一个算法,每当生活中出现一些烦心事,这个算法都能给我终极的答案。这就是一个好的算法的威力所在。

另外一种描述算法的方法是基于伪代码方式,如图1-12所示。比起流程图,它更加精练,也更贴近实现算法的代码,所以目前伪代码的表示方式应用得比较广。

图1-12 Algorithm 1

你想知道Algorithm 1 是怎么生成的吗?其实我早就等你问这个问题了!首先它不是画出来的,而是自动生成的。它是用LaTeX 软件并利用了algorithm2e.sty 包编写完成的。生成Algorithm 1 的Latex 源码内容如图1-13 所示。有了LaTeX 下这些功能扩展包,撰写计算机语言的书籍变得如此便捷和充满乐趣。有关LaTeX 的一本经典参考书是《The Latex Companion》 [9]

LaTeX 与Word 是目前两种主流的文本编辑系统,在使用便捷性和学习难度上,Word 明显优于LaTeX,这点从Algorithm 1 的LaTex 源码上你就能有所体会。仅“所见即所得”一项,LaTeX 就弱爆了。但如果应用在学术报告、科技论文以及教材方面,Word 就有些力不从心了。至少如此美观、整齐的Algorithm 1,利用Word 是很难高质量、大批量地生成出来。关于LaTeX 与Word 的区别,大家可以参考本书网站上“扩展内容”网页中的“LaTex 和Word 的不同”。

图1-13

LaTeX是基于TeX的一个排版系统,TeX是一个很好的排版工具,特别是在处理复杂的数学公式时。提起TeX,就必须提到它的开发者、大名鼎鼎的美国计算机教授高德纳(Donald E. Knuth)。高教授还撰写了《The Art of Computer Programming》一套书,计划写7卷,目前完成了前4卷。本套书在1999年底被美国国家期刊(American Scientist)列为20 世纪最佳12部学术专著之一,与狄拉克的量子力学、爱因斯坦的相对论齐名。

在中国,本书被称为算法领域的“葵花宝典”。光凭“葵花宝典”这个比喻,就已经吓得我直到现在都没有胆量去读。所以我选择了一本相对初级的“独孤九剑”来读,那就是《算法导论》 [10] 。等以后我的功力增长到一定程度,再和媳妇商量商量,然后再去读“葵花宝典”。

算法很有用,但是,算法真的很难学,需要一些抽象的思维和数学基础,不是一朝一夕就能搞定的。我的建议是,如果你立志当一名程序员,就要把学算法、用算法当成毕生的事情,所以我们的口号就是:“随时随地快乐学”。记住,任何一本算法书都应该随时、随地拿来读,不要指望着几天读完了事、收工。 SS7oJdLNUxw7JfLxPdiuYUq0RCIkbwrOJyd/f5VNsuOiW5F9hRfGu5RAyrwURE5g

点击中间区域
呼出菜单
上一章
目录
下一章
×