3.1 渐进记号
一.
1.引言
当输入规模足够大时,使得只有运行时间的增长量级有关时,我们要研究算法的渐进效率。也就是说,我们关心当输入规模无限增加时,在极限中,算法的运行时间如何随着输入规模的变大而增加。通常,渐进地更有效的某个算法对除很小的输入外的所有情况将是最好的选择。
2.定义
用来描述算法渐进运行时间的记号根据定义域为自然数集 N = {0, 1, 2, …}的函数来定义。
然而,我们发现有时按各种方式活用渐进记号是方便的。例如:我们可以扩展该记号到实数域或者选择性地限制其到自然数的一个子集。
3.渐进记号、函数与运行时间
渐进记号也可以适用于刻画算法的某个其他方面(例如,算法使用的空间数量)的函数,甚至可以适用于和算法没有任何关系的函数。
3.1. Θ 记号
3.1.1.定义
对给定的函数 g(n) ,用 Θ(g(n)) 来表示以下函数的集合:
Θ ( g ( n ) ) = { f ( n ) : 存 在 正 常 量 c 1 、 c 2 和 n 0 , 使 得 对 所 有 n ≥ n 0 , 有 0 ≤ c 1 g ( n ) ≤ f ( n ) ≤ c 2 g ( n ) } \Theta(g(n)) = \{ f(n):存在正常量c_1、c_2和n_0,使得对所有n≥n_0,有0≤c_1g(n)≤f(n)≤c_2g(n)\} Θ(g(n))={
f(n):存在正常量c1、c2和n0,使得对所有n≥n0,有0≤c1g(n)≤f(n)≤c2g(n)} 因为 Θ(g(n)) 是一个集合,所以可以记 f ( n ) ∈ Θ ( g ( n ) ) f(n) \in \Theta(g(n)) f(n)∈Θ(g(n)) 以指出 f(n) 是 Θ(g(n)) 的成员。作为替代,我们通常可以记 f ( n ) = Θ ( g ( n ) ) f(n) = \Theta(g(n)) f(n)=Θ(g(n)) 以表达相同的概念。
3.1.2.渐进紧确线
如图 3-1(a) 所示:
对在 n0 及其右边的所有值, f(n) 的值位于或高于 c1g(n) 且位于或低于 c2g(n) 。换句话说,对所有 n ≥ n0 ,函数 f(n) 在一个常量因子内等于 g(n) 。我们称 g(n) 是 f(n) 的一个渐进紧确界。
Θ(g(n)) 的定义要求每个成员 f(n) ∈ Θ(g(n)) 均渐近非负,即当 n 足够大时,f(n) 非负。(渐进正函数就是对所有足够大的 n 均为正的函数。)因此,函数 g(n) 必须本身渐近非负,否则集合 Θ(g(n)) 为空。所以我们假设用在 Θ 记号中的每个函数均渐近非负。
一般来说,对任意多项式 p ( n ) = ∑ i = 0 d a i n i , 其 中 a i 为 常 量 且 a d > 0 p(n)=\sum_{i=0}^{d}a_in^i,其中a_i为常量且a_d>0 p(n)=i=0∑daini,其中ai为常量且ad>0 我们有 p ( n ) = Θ ( n d ) p(n) = \Theta(n^d) p(n)=Θ(nd)
因为任意常量是一个 0 阶多项式,所以可以把任意常量函数表示成 Θ(n0) 或 Θ(1) 。然而,后一种记号是一种轻微的活用,因为该表达式并未指出什么变量趋于无穷(真正的问题是通常的函数记号没有区分函数与函数值。在 λ 演算中,函数的参数被清楚地说明:函数 n2 可被写成 λn.n² ,或者甚至写成 λr.r² 。然而一种更严格的记号将使代数操作复杂化,所以我们选择容忍这种活用)。我们将经常使用记号 Θ(1) 来意指一个常量或者关于某个常量的一个常量函数。
3.2. O 记号
3.2.1.定义
Θ 记号渐近地给出一个函数的上界和下界。当只有一个渐进上界时,使用 O 记号。对于给定的函数 g(n),用 O(g(n)) (读作“大Og(n)”,有时仅读作“Og(n)”)来表示以下函数的集合:
O ( g ( n ) ) = { f ( n ) : 存 在 正 常 量 c 和 n 0 , 使 得 对 所 有 n ≥ n 0 , 有 0 ≤ f ( n ) ≤ c g ( n ) } O(g(n))=\{f(n):存在正常量c和n_0,使得对所有n≥n_0,有0≤f(n)≤cg(n)\} O(g(n))={
f(n):存在正常量c和n0,使得对所有n≥n0,有0≤f(n)≤cg(n)}
3.2.2.记号
如图 3-1(b) 所示,O 记号为函数给出一个在常量因子内的上界。如果存在正常量 n0和 c,使得在 n0及其右边,f(n) 的值总小于或等于 cg(n),那么记 f ( n ) = O ( g ( n ) ) f(n)=O(g(n)) f(n)=O(g(n)) 以指出函数 f(n) 是集合 O(g(n)) 的成员。注意, f ( n ) = Θ ( g ( n ) ) ⇒ f ( n ) = O ( g ( n ) ) , 即 Θ ( g ( n ) ) ⊆ O ( g ( n ) ) f(n)=\Theta(g(n))\Rightarrow f(n)=O(g(n)),即\Theta(g(n))\subseteq O(g(n)) f(n)=Θ(g(n))⇒f(n)=O(g(n)),即Θ(g(n))⊆O(g(n)) 在文献中,O 记号有时候非形式化地描述渐近确界,即已经使用 Θ 记号定义的东西。
当我们说“运行时间为 O(n2) ”时,意指存在一个 O(n2) 的函数 f(n),使得对 n 的任意值,不管选择什么特定的规模为 n 的输入,其运行时间的上界都是 f(n)。这也就是说最坏情况运行时间为 O(n2)。
3.3. Ω 记号
3.3.1.定义
正如 O 记号提供了一个函数的渐近上界,Ω 符号提供了渐近下界。对于给定的函数 g(n),用 Ω(g(n)) (读作“大 Ωg(n)”,有时仅读作“ Ωg(n) ”)来表示以下函数的集合: Ω ( g ( n ) ) = { f ( n ) : 存 在 正 常 数 c 和 n 0 , 使 得 对 所 有 n ≥ n 0 , 有 0 ≤ c g ( n ) ≤ f ( n ) } \Omega(g(n))=\{f(n):存在正常数c和n_0,使得对所有n≥n_0,有0≤cg(n)≤f(n)\} Ω(g