上一课算法和数据结构-初级
第二课:小鸭子们去旅行中,我们讲了一个有趣的小故事,就是为了引出算法复杂度。
算法复杂度非常重要,要讲的内容也很多,所以我们分为上下两课。
当程序员需要解决计算机科学相关的问题时,他们(通常)会编写一个程序。这个程序包含一个实现,也就是说需要把算法用一种编程语言来实现。
我们知道,算法只是对解决问题的步骤的一种精确描述,它并不依赖于程序员所用的编程语言或工作环境。
我们在算法和数据结构-初级
第一课:什么是算法和数据结构里介绍了一个“煮方便面”的食谱,这份食谱虽然简单,但可以说是一个算法。
我们是用中文来描述这份食谱的,如果我现在把这份食谱翻译成一门外语(比如英语),但食谱的内容还是不变,只不过换了一种语言来说明罢了。换个英国人来照着这份英文食谱煮方便面,跟我做出来的会是一样的。
那么,当程序员需要把算法用一种编程语言来实现时,需要做什么呢?
像农夫Oscar一样,他必须首先验证他的算法是正确的,也就是说它产生了预期的结果,解决了所涉及的问题。这非常重要(如果算法不正确,那我们根本没有选择和优化它的必要),有时验证算法正确性是非常难的一步。
算法的正确性,英语是AlgorithmCorrctnss。要证明算法的正确性,有许多方法,我们本课程就不详述了,因为这不是我们的重点。大家有兴趣可以去网上搜索一下。
当然,算法正确了,并不能保证实现这个算法的程序就没有错误(bug)。
一旦有了一个正确的算法,我们用编程语言去实现它(通过编写一个执行它的程序)。但我们可能会写出有很多小错误的程序,这些小错误也许和所使用的编程语言有关,可能在编写程序的过程中被引入。因为算法中一般不会描述如何避免犯错,例如如何管理程序的内存,如何检查段错误(SgmntationFault),等等,但这些都是程序员实现算法时需要考虑的问题。
2.算法的复杂度一旦程序员确信他的算法是正确的,他将尝试评估其效率,比如他会想知道“这个算法快不快”。
有人可能会认为,要知道算法快不快的最佳方式是实现该算法并在电脑上进行测试。
有趣的是,通常情况并非如此。例如,如果两个程序员实现了两种不同的算法,并在各自的电脑上测试程序运行的快慢。那么拥有更快速度的电脑的那个程序员可能会错误地认为他的算法更快,但其实并不一定。
而且,要实现一个算法并测试,有时候并不容易。且不说有时候根据一个算法来写出实现的代码很难,如果要实现的算法涉及到一枚火箭的发射,难道每次用一枚真的火箭来发射一下去测试算法快不快吗?我们又不像钢铁侠那么有钱可以任性。
钢铁侠
出于这些原因,计算机科学家们发明了一个非常方便而强大的概念,也就是我们接下来要学习的:算法的复杂度。
“复杂度”(Complxity,表示“复杂”,是一个名词。它对应的形容词是Complx,表示“复杂的”)这个词有点误导人,因为我们这里不是强调“理解起来有困难”(很复杂,很难),而是指效率(Efficincy)。
“复杂度”并不意味着“复杂的程度”。有的算法理解起来很难(很复杂),它的复杂度却可以非常低。
如果要用一句话来简单说明算法复杂度,那可以是:
“如果给实现了这个算法的程序一个大小为N的输入,那么这个程序将执行的操作的数目的数量级是N的一个怎么样的函数(f(N))呢?”
f(N)中的f是function(函数)的意思,相信以前数学课的时候,大家都学过(比如我们以前很常见的y=f(x))。f(N)表示“N的函数”。
上面那句话基于以下事实:解决问题的程序取决于问题的起始条件。如果起始条件改变,程序执行的时间也会变长或变短。
复杂度可以量化(通过数学公式)起始条件与算法执行的时间之间的关系。
上面这几句话乍看有点难以理解。什么是操作?什么是操作的数目,什么是操作的数目的数量级?
不用担心,我们慢慢讲解:
复杂度的学习中会涉及一些数学的概念。所以嘛,学好数学对编程还是很有帮助的,英语同样很重要。如果你英语和数学比较好,学起编程来会轻松很多。可以参看我以前的一篇文章:对于程序员,为什么英语比数学更重要?如何学习
数量级是指数量的尺度或大小的级别,每个级别之间保持固定的比例。通常采用的比例有10,2,,,(欧拉数,大约等于2.的超越数,即自然对数的底)。
--摘自百度百科北京去哪里医院治疗白癜风最好宝宝白癜风能治好吗