算法分析

数据结构是组织和访问数据的一种系统化方式,算法是在有限的时间里一步步执行某些任务的过程。
我们在本文中用到的主要分析方法包括算法和数据结构的运行时间和空间利用表示。

实验研究

如果算法已经实现了,我们可以通过在不同的输入下执行它并记录每一次执行所花费的时间来研究它的运行时间。Python中一个简单的实现方法是使用time模块的time()函数。这个函数传递的是自新纪元基准时间后已经过去的秒数或分数(新纪元是指1970年)。当我们可以通过记录算法运行前的那一刻以及算法执行完毕后的那一刻也,并且计算它们之间的差来判定消逝的时间时,新纪元的选择不影响测试事件的结果。

7种函数

常数函数

f(n) = c
最基本的常数函数是g(n) = 1,注意:任何其他的函数 f(n) = c都可以写成常数c乘以g(n),即f(n)=cg(n)。

对数函数

数据结构和算法分析中最令人感兴趣的甚至惊奇的是无处不在的对数函数,f(n)=logbn,常数b>1。此函数定义如下:
x = logbn 当且仅当bx=n
按照定义,logb1=0,b是对数的底数。
在计算机科学中,对数函数最常见的底数是2,因为计算机存储整数采用二进制,并且许多算法中的常用操作是反复把一个输入分成两半。事实上,这个底数相当常见,以至于当底数等于2时,我们通常会省略它的符号,即:logn = log2n

线性函数

另一个简单却很重要的函数时线性函数,
f(n)=n
即,给定输入值n,线性函数f就是n本身。
这个函数出现在我们必须对所有n个元素做基本操作的算法分析的任何时间。比如,比较数字x和大小为n的序列中的每一个元素,需要做n次比较。

n log n函数

f(n) = n log n
对于一个输入值n,这个函数是n倍的以2为底的n的对数。这个函数的增长速度比线性函数快,比二次函数慢。因此,与运行时间是二次的算法相比较,我们更喜欢运行时间与n log n成比例的算法。我们会看到一些运行时间与n log n成比例的重要算法。例如:对n个任意数进行排序且运行时间与n log n成比例的最快可能算法。

二次函数

f(n) = n2
二次函数用在算法中的主要原因是,许多算法中都有嵌套循环,其中内存循环执行一个线性操作数,外层循环则表示执行线性操作数的次数。因此,在这个情况下,算法执行了n*n = n2个操作。

三次函数和其他多项式

f(n) = n3
这个函数在算法分析文章中出现的频率较低,但它确实会时不时出现。

多项式

f(n)=a0+a1n+a2n2+a3n3+...+adnd
例如,下面所有函数都是多项式
1 f(n) = 2 + 5n + n2
2 f(n) = 1 + n2
3 f(n) = 1
4 f(n) = n
5 f(n) = n2

指数函数

f(n) = bn
其中b是一个正的常数,参数n是指数。在算法分析中,指数函数最基本的情况是b=2。如果通过一个操作执行一个循环,然后每次迭代所执行的操作数目翻倍,则在第n次迭代所执行的操作数目为2n
从事计算工作的每个人都应该知道
1 + 2 + 4 +8 +...+ 2n-1 = 2n -1

比较增长率

综上所述,按顺序给出的算法分析使用的7个常用函数如下图所示:

常数函数 对数函数 线性函数 n logn函数 二次函数 三次函数 指数函数
1 log n n n logn n2 n3 an

理想情况下,我们希望数据结构的操作时间与常数函数或者对数函数成正比,而且我们希望算法以线性函数或nlogn函数来运行。运行时间为二次或者三次的算法不太实用,除最小输入规模的情况外,运行时间为指数的算法是不可行的。7个函数的增长率如下图所示:


算法分析_第1张图片
image.png

渐近分析

在算法分析中,我们重点研究运行时间的增长率,采用宏观方法把运行时间视为输入大小为n的函数。例如:同行只要知道算法的运行时间按比例增长到n就足够了。

大O符号

令f(n)和g(n)作为正实数映射正整数的函数。如果有实型常量c>0和整型常量n0>=1满足:
f(n) <= cg(n),当n>=n0
我们就说f(n)是O(g(n))。有时被说成"f(n)是g(n)的大O"
例如:函数8n+5是O(n)
使用大O符号描述运行时间
通过设定一些参数n,大O符号被广泛用于描述运行时间和空间界限。
命题:找最大数算法(即计算一系列数中的最大数)的运行时间为O(n)
大O符号的一些性质
大O符号使得我们忽视常量因子和低阶项,转而关注函数中影响增长的主要成分。
例如:
5n4 +3n3+2n2+4n+1是O(n4)
证明:注意,5n4 +3n3+2n2+4n+1<=(5+3+2+4+1)n4=cn4,令c=15,当n>=n0=1时,即满足题意。
事实上,我们可以描述任何多项式函数的增长速率。
如果f(n)是一个指数为d的多项式,即:f(n)=a0+a1n+a2n2+a3n3+...+adnd
且ad>0,则f(n)是0(nd)。
因此,多项式中的最高阶项决定了该多项式的渐进增长速率。

你可能感兴趣的:(算法分析)