1.1 算法的规范化和量化度量
对计算机科学贡献最大的人
图灵提出了计算机的数学模型
冯·诺依曼确定了计算机通用的系统结构
高德纳则奠定了计算机算法的基础
计算机的组成
计算和存储部分的硬件+程序->计算机
程序的灵魂在于算法
在早期的计算机中,哪些控制功能要通过开关电路做成硬件(虽然当时还没有硬件的提法)、哪些由程序控制,这个边界很不清晰。
人类第一台电子计算机ENIAC实际上是一种专用计算机,专门用于解决研制长程火炮过程中的计算问题。
冯·诺依曼当时负责美国氢弹工程,需要进行大量的计算,听说有人正在研制电子计算机,就跑去看看能否也解决氢弹计算的问题。冯·诺依曼发现了他们的问题,留下一句话:如果将来要让它计算其他问题,也并非完全不可能,修改线路就可以了,但是会特别麻烦。后来虽然ENIAC也被用于进行其他计算,但是每一次改电路实在是太麻烦。
所幸的是,军方在ENIAC研制成功前了解了这个情况,并且在1944年决定再造一台新的、通用的计算机。于是冯·诺依曼和莫奇利、埃克特一起提出一种全新的设计方案,称为EDVAC(音译为艾迪瓦克,英文全称Electronic Discrete Variable Automatic Computer,离散变量自动电子计算机)。其实EDVAC才是世界上第一台程序控制的通用电子计算机,并且可以说是今天所有计算机的鼻祖。ENIAC则是一个孤版,因为它不通用。
EDVAC的意义在于它涵盖了一种通用的计算机的体系结构,并且告诉后人计算机这东西是需要顶层设计的。
冯·诺依曼在客观上将计算机分为了软硬件两部分。在随后的10多年里,整个行业关注比较多的是硬件。由于冯·诺依曼体系结构非常具有前瞻性,因此到了20世纪60年代,尽管计算机已经从电子管的、晶体管的,进入第三代集成电路的了,但是体系结构还是在冯·诺依曼设定的框架之中。
到了60年代,计算机在商业上开始普及,一个商业程序是要提供给很多用户反复使用的,程序设计得是否合理、效率的高低、占用资源的多少,就需要认真考虑了。这时,在计算机算法理论方面的缺失,就需要有人来弥补了。而奠定计算机算法基础的人正是我们这一节的主角——高德纳。
他是计算机算法分析的鼻祖,提出了评估计算机算法的标准。这是我们接下来要详细介绍的。
思考题1.1
世界上还有什么产品类似于计算机,是软硬件分离的?( 难度系数1颗星)
首先了解一下什么是软硬件分离,我的理解:一样的硬件可以跑不同的软件,进行不同的计算,实现不同的功能。
其他解释:就是解耦的意思,就是尽量相互独立。
题目问的是产品,经搜索答曰:数字电视、汽车......
1.2 大数和数量级的概念
不过,一个数量级的差别,即10倍,固然不小,但是相对于计算机算法最终造成的差异可以忽略不计,因为算法的优劣稍微差了一点,最后计算机运行的时间就很容易差出千万倍。
人其实本能地对大数没有什么概念,毕竟我们生活在一个小数的世界里。同样,我们对很快的速度也是没有概念的,因为我们生活在一个很慢的世界里。
由于人们天生对计算机资源没有直观的概念,总觉得它的速度无穷大,内存用不完,因此很多人会无端浪费很多资源。
今天,虽然计算机硬件的进步速度并不慢,大约是每10年提升100倍,但是在做产品的那一段特定时间里,硬件性能几乎是一个常数。而产品性能的差异就看软件了,而它又由里面的算法决定。
要衡量算法的好坏,就必须先明确算法的衡量标准以及测试的方法,这和任何其他科学的工作方法都一样。那么什么是好算法呢?很多人首先会想到“速度快”,占用内存空间小。这两个标准的大方向都没有错,关键在于用多少数据来测试算法的速度和空间,因为用不同数量的数据测试时,两个算法的相对表现可能会完全不一样。
最早将算法复杂度严格量化衡量的就是高德纳,他也因此被誉为“算法分析之父”。今天,全世界的计算机领域都以高德纳的思想为准。
高德纳的思想主要包括以下三个部分。
- 在比较算法的快慢时,只需要考虑数据量特别大,大到近乎无穷大时的情况。为什么要比大数的情况,而不比小数的情况呢?因为计算机的发明就是为了处理大量数据的,而且数据越处理越多。比如我和同学们做砸的那个对账功能,就是没有考虑数据量会剧增。
- 决定算法快慢的因素虽然可能有很多,但是所有的因素都可以被分为两类:第一类是不随数据量变化的因素,第二类是随数据量变化的因素。
- 两种算法在复杂度上相差哪怕只有一点点,N很大之后,效率可能就差出万亿倍了。比如用非常容易想到的选择排序或插入排序和专业人士常用的快速排序对10多亿个QQ号排一次序,计算量分别是大约100亿亿次和30亿次。对今天的大数据处理来讲,对10亿个QQ号排序并非一件大事,但是从这件事可以看出,如果选择的算法在复杂度的数量级上相差那么一点点,代码执行的效率就有天壤之别。
思考题1.2
如果一个程序只运行一次,在编写它的时候,你是采用最直观但是效率较低的算法,还是依然寻找复杂度最优的算法?(难度系数2颗星)
即使程序只运行一次,依然要考虑大量的数据处理时的时间问题,所以寻找复杂度较优的算法更好。