【从零开始学习计算机科学】算法分析(一)算法、渐进分析、递归分析
【从零开始学习计算机科学】算法分析(一)算法、渐进分析、递归分析
-
- 算法
- 算法分析
-
- 正确性
- 算法完成需要的时间
- 使用的存储空间
- 简单性
- 渐进分析
- 递归分析
-
- 主方法求解递归式
- 递归树求解
- 代入法
- 概率分析和随机算法
- 顺序统计量
算法
什么是算法?算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。
一个算法具有计算过程,计算问题,输入,输出等要素。其中,计算问题是指问题语句指定所需的输入/输出关系。计算过程描述了该算法实现该输入/输出关系的特定计算过程。
我们还可以将算法视为解决指定良好的计算问题的工具,在这个意义下,算法可以定义为任何良好的计算过程,其将一些值或一组值作为输入,然后生成一些值作为输出。在输入和输出的意义下,算法可以定义为将输入转换为输出的计算步骤序列。
算法可以通过自然语言、伪代码、计算机程序、硬件等等多种方式描述。唯一的要求是规范必须提供要遵循的计算过程的确切描述。
算法和思维是密不可分的,算法蕴含着思维的多种特性,算法本质上是思维的一种实例,是将计算思维的实例表述,算法反映着我们对于客观问题的主观意识,包含对问题的认知,看法,理解与思考。并且,算法是基于客观存在的问题出现的,任何一个算法,都是为了解决某些客观存在着的问题而出现的,其与问题是对立统一的,算法反映了我们对于客观问题的思维,体现着人的本质力量。
在当今条件下,一个算法应该具有以下五个重要的特征:
- 有穷性,算法的有穷性是指算法必须能在执行有限个步骤之后终止;
- 确切性,算法的每一步骤必须有确切的定义;
- 输入项,一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条件;
- 输出项,一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的;
- 可行性,算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步骤,即每个计算步骤都可以在有限时间内完成(也称之为有效性)。
一个算法不仅仅需要上述五个特征,我们一般还会要求算法满足正确性。算法的正确性是指如果对于每个输入实例,算法都使用正确的输出停止,则算法是正确的。不正确的算法可能在某些输入实例上完全不会停止,或者可能会以所需的答案以外的答案停止。但是,如果可以控制不正确的算法的错误率,则有时可能很有用,比如大多数机器学习算法。
本文仅介绍了一些非常常用的算法和算法分析的基础方法和理论,对于实际遇到的问题,我们还需要针对具体的问题设计并实现具体的算法。
算法分析
算法分析是指计算机程序性能和资源利用的理论研究。算法分析是为了提高算法性能而产生的一门学科。
对于算法的性能,我们需要采用一些标准来量化评估,目前我们通常使用以下标准:正确性,完成需要的时间,使用的存储空间,简单性,最优性。
正确性
如果给定有效输入时,算法计算时间有限并生成正确答案,则算法是正确的。如果我们知道什么是有效输入以及什么是正确答案,此定义会非常有用。因此,显示算法是正确的意味着在给定特定输入时对生成的结果进行精确陈述,然后证明该语句。
算法完成需要的时间
算法完成需要的时间取决于多种因素,即使在相同环境下,算法的运行时间也不一定相同(比如随机算法)。
目前,我们通常使用的计算模型是RAM(随机访问计算机)模型。在 RAM 模型中,指令将一个又一个地执行,没有并发操作。
RAM 模型的操作
- 算术运算:加、减、乘、除、余、最小值,最大值等等。
- 逻辑运算:与、或、非、大于、小于、等于、不等于等等。
- 数据移动与控制:加载、存储、复制,有条件和无条件分支、子例程调用和返回。
我们可以通过RAM模型描述算法完成需要的时间:
- 输入:什么样的输入?(I)
- 输入大小(输入规模):多大的规模?在RAM模型中为指令的数目 ( n 1 , n 2 , … , n k ) (n_1,n_2,\ldots,n_k) (n1,n2,…,nk)。
- 机器:CPU 机器的速度? ( v 1 , v 2 , … , v k ) (v_1,v_2,\ldots,v_k) (v1,v2,…,vk)
- 计算模型:RAM(随机访问计算机)机器的个数?(m)
一般来说,我们寻求运行时间上限,即算法最慢完成需要的时间。在忽略其他因素的影响下,运行时间由完成的基本操作数和 cpu 速度决定,运行时间:t = sum { n 1 / v 1 , … , n k / v k } \{n_1/v_1,\ldots,n_k/v_k\} { n1/v1,…,nk/vk}。
算法完成需要的时间是与机器无关的运行时间,即t独立于不同的机器环境,因此,其忽略与机器相关的常量。并且,一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数