當輸入規模足夠大時,使得只有運行時間的增長量級有關時,我們要研究算法的漸近效率。也就是說,我們關心當輸入規模無限增加時,在極限中,算法的運行時間如何隨着輸入規模的變大而增加。通常,漸近地更有效的某個算法對很小的輸入外的所有情況將是最好的。
本章給出幾種標準方法來簡化算法的漸近分析。下一節首先定義幾類“漸近記號”,其中,我們已經見過一個例子是Θ記號。然後,我們給出貫穿本書使用的幾種記號的約定。最後,回顧以下在算法分析中常見的若干函數的行爲。
3.1 漸近記號
用來描述算法漸近運行時間的記號根據定義域爲自然數集N={0,1,2,……}的函數來定義。這樣的記號對描述最壞情況運行時間函數T(n)是方便的,因爲該函數通常只定義在整數輸入規模上。
漸近記號、函數與運行時間
我們將主要用漸近記號來描述算法的運行時間。然而,漸近記號實際應用與函數。
本書中對其使用漸近記號的函數通常刻畫算法的運行時間。但是漸近記號也可以適用於刻畫算法的某個方面的函數,甚至可以適用於和算法沒有關係的函數。
Θ記號
在第 2 章,我們發現插入排序的最壞情況運行時間T(n)=Θ(
Θ(g(n)) = { f(n):存在常量c1、c2和n0,使得對所有n ≥ n0,有 0 ≤ c1g(n) ≤ f(n) ≤ c2g(n) }
若存在常量c1和c2,使得對於足夠大的n,函數f(n)能“夾入”c1g(n) 與 c2g(n)之間,則f(n) 屬於集合Θ(g(n))。因爲Θ(g(n))是一個集合,所以可以記爲“f(n) ∈ Θ(g(n))”,以指出f(n)是Θ(g(n))的成員。作爲替代,我們通常記爲“f(n) = Θ(g(n))”以表達相同的概念。
換句話說,對所有 n ≥ n0,函數f(n)在一個常量因子內等於g(n)。我們稱g(n) 是 f(n) 的一個漸近緊確界。
Θ(g(n))的定義要求每個成員f(n) ∈ Θ(g(n))均漸近非負,即當 n 足夠大時,f(n)非負。因此,函數g(n)本身必爲漸近非負,否者集合Θ(g(n))爲空。所有我們假設用在 Θ 記號的每個函數均漸近非負。這個假設對本章定義的其他漸近號也成立。
一般來說,對任意多項式p(n) =
因爲任意常量是一個 0 階多項式所以可以把任意常量函數表示成Θ(
Ο記號
Θ記號漸近地給出了一個函數的上界和下界。當只有一個漸近上界時,使用O記號。對於給定的函數g(n) ,用O(g(n))來表示以下函數的集合:
O(g(n)) = { f(n)存在正常量c和
我們記f(n)=O(g(n))以指出函數f(n)是集合O(g(n))的成員。按集合論的寫法,我們有Θ(g(n)) ⊆ O(g(n))。
當我們說“運行時間爲O(
Ω記號
Ω記號提供了漸近下界。對於給定的函數g(n),Ω(g(n))來表示以下函數的集合:
Ω(g(n))={f(n):存在正常量c 和
定理 3.1 對任意兩個函數f(n)和g(n),我們有f(n)=Θ(g(n)),當且僅當f(n)=O(g(n))且f(n)=Ω(g(n)).
當稱一個算法的運行時間爲Ω(g(n))時,我們意指對每個n值,不管選擇什麼特定的規模爲n的輸入,只要n足夠大,對那個輸入的運行時間至少是g(n)的常量倍。等價地,我們在對一個算法的最好情況運行時間給出一個下界。
等式和不等式中的漸近記號
當漸近記號獨立於等式的右邊時,我們已經定義等號意指集合的成員關係。然而,一般來說,當漸近號出現在某個公式中時,我們將其解釋爲代表某個我們不關注名稱的匿名函數。例如,公式
按這種方式使用漸近記號可以幫助消除一個等式中無關緊要的細節與混亂。
o記號
由O記號提供的漸近上界可能是也可能不是漸近緊確的。我們使用o記號來表示一個非漸近緊確的上界。形式化地定義o(g(n))爲以下集合:
o(g(n))={f(n):對任意正常量c>0,存在常量
O記號與o記號類似。主要區別是在f(n)=O(g(n))中,界
有些學者使用這個極限作爲o記號的定義;本書中的定義還限定匿名函數是漸近非負的。
ω記號
ω與Ω的關係類似與o記號與O記號的關係。我們使用ω記號來表示一個非漸近緊確的下界。定義它的一種方式是:
f(n) ∈ ω(g(n))當且僅當g(n) ∈ o(f(n))
然而,我們形式化第定義ω(g(n))爲以下集合:
ω(g(n))={f(n):對任意正常量c>0,存在常量
關係f(n)=ω(g(n))蘊含着:
也就是說,如果這個極限存在,那麼當n趨於無窮大時,f(n)相對於g(n)來說變得任意大了。
比較各種函數
實數的許多關係性質也使用於漸近比較。下面假定f(n)和g(n)漸近爲正。
傳遞性:
f(n)=Θ(g(n)) 且 g(n) = Θ(h(n)) 蘊含f(n)=Θ(h(n))
f(n)=O(g(n)) 且 g(n) = O(h(n)) 蘊含f(n)=O(h(n))
f(n)=Ω(g(n)) 且 g(n) = Ω(h(n)) 蘊含f(n)=Ω(h(n))
f(n)=o(g(n)) 且 g(n) = o(h(n)) 蘊含f(n)=o(h(n))
f(n)=ω(g(n)) 且 g(n) = ω(h(n)) 蘊含f(n)=ω(h(n))
自反性
f(n) = Θ(f(n))
f(n) = O(f(n))
f(n) = Ω(f(n))
對成型
f(n) = Θ(g(n)),當且僅當g(n)=Θ(f(n))
轉置對成性
f(n) = O(g(n))當且僅當g(n)= Ω(f(n))
f(n) = o(g(n))當且僅當g(n)= ω(f(n))
因爲這些性質對漸近記號成立,所以可以在兩個函數f和g的漸近比較和兩個實數a與b的比較之間做一種類比。
f(n)=O(g(n)) 類似於a
f(n)=Ω(g(n)) 類似於a
f(n)=Θ(g(n)) 類似於a
f(n)=o(g(n)) 類似於a
f(n)=ω(g(n)) 類似於a
若f(n)=o(g(n)),則稱f(n)漸近小於**g(n);若f(n)=ω(g(n)),則稱f(n)漸近大於**g(n);
然而,實數的下列性質不能攜帶到漸近記號:
三分性:對任意兩個實數a和b,下列三種情況恰有一種必須成立:a
3.2 標準記號與常用函數
本節將回顧一些標準的數學函數與記號並探索它們之間的關係
單調性
若
向下取整與向上取整
對任意實數x,我們用⌊x⌋表示小於或等於x的最大整數(讀作“x的向下取整”),並用⌈x⌉表示大於或等於x的最小整數(讀作“x的向上取整”)。對所有實數x,
x-1<⌊x⌋
對任意實數n,⌊n/2⌋+⌈n/2⌉ = n
對任意實數x
⌈
⌊
⌈
⌊
向下取整函數f(x)=⌊x⌋是單調遞增的,向上取整函數f(x)=⌈x⌉也是單調遞增的。
模運算
對任意整數a和任意正整數n,a mod n的值就是a/n的餘數:
a mod n=a-n⌊a/n⌋
若(a mod n)=(b mod n),則記a
多項式
給定一個非負整數d,n的d次多項式爲具有以下形式的一個函數p(n):
其中,常量
指數
對所有實數a>0、m和n,我們有以下恆等式:
對所有n和
可以通過以下事實使多項式與指數的增長率互相關聯。對所有使得a>1的實常量a和b,有
據此可得:
因此,任意底大於 1 的指數函數比任意多項式函數增長的快。
使用e來表示自然對數函數的底2.71828…,對所有實數x,我們有
其中“!”表示本節後面定義的階乘函數。對所有實數x,我們有不等式:
其中只有當x=0是等號成立。當
當
對所有x,我們有:
對數
我們將使用下面的記號:
對所有實數a>0,b>0,c>0和n,有
其中,上面的每個等式中,對數的底不爲1.
若對某個常量k,f(n)=O(
對任意常量a>0,
階乘
記號n!定義爲對整數
階乘的一個弱上界是
給出了一個更緊確的上界和下界。
對所有
其中,
多重函數
我們使用記號
例如,若f(n)=2n,則
多重對數函數
我們使用
多重對數函數是一個增長非常慢的函數:
斐波那契數
使用下面的遞歸式來定義斐波那契數:
因此,每個斐波那契數都是兩個前面的數之和。
斐波那契數與黃金分割率
特別地有:
因爲|
這蘊含着
這就是說第i個斐波那契數