您的位置:首页 > 其它

【算法导论】分析算法

2016-11-16 23:49 337 查看
分析算法的结果意味着预测算法需要的资源。虽然有时候我们主要关心像内存、计算机硬件、通信带宽这类的硬件资源,但是通常我们想度量的是计算时间。一般来说,通过分析求解某个问题的几种候选算法,我们在其中选择一种最有效的算法。这种分析可能会指出不止一个的可行的候选算法,但是在这个过程中,我们往往可以抛弃几个较差的算法。

在能够分析一个算法之前,我们必须要有一个能使用实现技术的模型,包括描述所用的资源及其代价的模型。我们假定一种通用的单处理器计算模型——随机访问机(RAM)来作为我们的实现技术,算法可以用计算机程序来实现,在RAM模型中,指令一条一条执行,没有并发操作。RAM模型包含真实计算机中常见的指令:算术指令、数据移动指令和控制指令。每条这样的指令所需的时间都为常量.在RAM中,我们没有对高速缓存和虚拟内存进行建模。与RAM相比,包含内存层次的模型要复杂的多,所以难以使用。
采用RAM模型即使分析一个简单的算法也可能是一种挑战,需要的数学工具可能包括组合学、概率论、代数技巧、以及识别一个公式中最有意义的项的能力。

插入排序算法的分析
插入算法的时间依赖于输入:排序1000个数比排序三个数需要更长的时间。此外,依据它们已被排序的程度,插入算法可能需要不同数量的时间来排序两个具有相同规模的输入序列。一般来说,算法需要的时间与输入的规模同步增长,所以通常把一个程序的运行时间描述成其输入规模的函数。
输入规模的最佳概念依赖于研究的问题,对于许多问题,如排序或者计算离散傅里叶变换,最自然的量度就是通常的二进制记号表示输入所需的总位数。
一个算法在特定输入上运行时间是指执行的基本操作数或步数。定义“步”的概念已便尽量独立于机器是方便的。执行每行代码所需的常量时间,虽然一行与另一行可能需要不同数量的时间。
即使对给定规模的输入,一个算法的时间也可能依赖于给定的规模下的哪个输入。例如:在插入排序中,若输入数组已经排好序,则出现最佳的情况,该最佳运行时间是an+b,其中a,b依赖于语句代价ci,因此它是n的线性函数。若输入数组已经反向排序,即按递减序排好序,则导致最坏的情况。最坏情况运行的时间表示为an^2+bn+c,其中常量a,b和c又依赖于语句代价ci,因此它是n的二次函数。

最坏情况和平均情况的分析:
在插入排序中,我们研究了最佳情况,其中输入数组已排好序,又研究了最坏的情况,其中输入数组已反向排好序。然而,我们往往集中于只求最坏的情况运行时间,下面给出三点理由:
1)一个算法的最坏情况运行时间给出了任何输入的运行时间的一个上界,知道了这个界,就能确保该算法绝不需要更长的时间。
2)对于某些算法,最坏的情况经常出现。
3)“平均情况”往往与最坏的情况大致一样差。假定随机选择n个数并应用插入排序。需要长时间来确定在子数组A[1,2.......j-1]的什么位置插入A[j]?平均来说,A[1,2......j-1]中一半元素小于A[JJ],一半的元素大于A[j],所以平均来说,我们检查子数组A[1,2......j-1]的一半,。那么tj大约为j/2。导致平均情况运行时间结果像最坏情况运行时间一样,也是输入规模的一个二次函数。

在某系特定的情况下,我们会对一个算法的平均情况感兴趣。我们常常假设给定规模的所有输入具有相同的可能性,实际上,该假设可能不成立,但是,有时候可以使用随机算法,它做出一些随机的选择,以允许进行概率分析并产生某个期望的运行时间。

增长量级
我们使用某些简化的抽象来使算法分析的过程更加容易。首先,通过使用常量ci表示这些代价来忽略每条语句的实际代价。其次,注意到这些常量比我们真正需要的更多的细节:把最坏情况的运行时间表示为an^2+bn+c,其中常量a,b,c依赖于语句代价ci,这样,我们不但忽略实际的语句代价,而且也忽略了抽象的代价ci。
现在做出更简化的抽象:我们真正感兴趣的运行时间的增长率或增长量级。所以我们只考虑公式中最重要的项(例如an^2),当n很大时,低阶项相对于来说不太重要,我们也忽略了最重要项的常系数,因为对对大的输入,在确定计算效率时常量因子不如增长率重要。对于插入排序,当我们忽视低阶项和最重要项的常系数时,只剩下最重要的项中的因子n^2。
如果一个算法的最坏情况运行时间具有比另一个算法更低的增长量级,那么我们通常认为前者比后者更有效。对于小的输入,运行时间具有较高的增长量级的一个算法与运行时间具有较低增长的另一个算法相比,可能需要更短的运行时间。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: