《演算法設計與分析》一一1 3 抽象演算法分析

2021-09-23 09:41:21 字數 4585 閱讀 4976

1.3 抽象演算法分析

面對乙個演算法問題,當我們已經為之設計乙個正確演算法的時候,下乙個關鍵問題就是分析所設計的演算法是否高效。為此,首先需要針對抽象演算法設計的特點,討論抽象演算法的效能指標。以此為基礎,進一步討論演算法的最壞情況和平均情況複雜度分析。

1.3.1 抽象演算法的效能指標

演算法效能分析的主要任務是度量演算法執行所消耗的資源,而這樣的資源主要體現在時間和空間這兩個方面。這一問題表面上看很簡單:要度量乙個演算法執行的時間,就直接記錄其執行的物理時間;度量乙個演算法執行所耗的空間,就直接度量演算法執行需要的儲存空間的位元數。

這一做法看似精確,其實存在較大的侷限。因為乙個演算法的實際執行的物理時間和儲存空間是與執行平台相關的,也是與實現語言相關的,另外還與執行環境中的諸多其他因素相關。這一度量看似精確,其實它依賴的具體因素太多,反而未能準確表徵演算法的效能好壞。從計算模型的角度來看,由於我們是在ram模型上設計抽象的演算法,所以演算法效能度量指標也應該具有機器無關、實現語言無關的特徵,同時它還需要能夠較為準確地表徵演算法的效能。

乙個在度量的一般性和精確性之間取得較好權衡的時間複雜度指標是ram模型上執行簡單操作的個數。執行操作的個數在很大程度上決定了演算法執行的快慢,乙個演算法的具體實現的具體執行時間,同其執行操作的個數往往具有線性關係。類似地,對於空間複雜度,我們可以直接用演算法需要用到的ram模型中暫存器的個數來度量。這一組效能指標源自於抽象的ram模型,所以它也具有機器無關、實現語言無關的抽象性,能夠較好地表徵乙個抽象演算法的效能。這樣,我們就將抽象演算法分析的問題變成了乙個計數(counting)問題:統計簡單操作的個數和儲存單元的個數。

在實際的演算法分析中,我們還可以對簡單操作的個數這一指標作進一步的精煉。在演算法分析時,我們往往並不關心所有的簡單操作,而是僅關注一些所謂的關鍵操作(critical operation)。這主要是因為,演算法執行的大量簡單操作都是輔助性的,並不是演算法運作的核心,並且乙個演算法執行的輔助性的簡單操作,其個數往往和關鍵操作的個數滿足乙個線性關係,所以關鍵操作的個數能夠準確表徵演算法的效能,同時它還大幅簡化了演算法分析。例如,在排序演算法分析中,我們著重關注的是元素的比較(comparison of keys)這一關鍵操作。一方面,元素的先後順序完全是由元素之間的兩兩比較的結果來決定的;另一方面,雖然排序必不可少地需要進行其他簡單操作,如儲存單元的讀寫、輔助變數的建立與修改等,但是這些輔助性的簡單操作的執行,主要是由元素的比較決定的,它們的個數也不超過元素比較個數的某乙個倍數。很多情況下,演算法的關鍵操作是不言自明的,必要的時候我們可以在演算法分析之前,明確約定演算法的關鍵操作。常見演算法問題中的關鍵操作如表1.1所示。

表1.1 常見演算法問題中的關鍵操作

演算法問題關鍵操作排序、選擇、查詢元素的比較圖遍歷節點資訊的簡單處理串匹配字元的比較矩陣運算兩個矩陣元素之間的簡單運算

有了度量演算法複雜度的指標,我們就可以進一步分析演算法的複雜度,進而比較演算法效能的好壞。這主要包括最壞情況複雜度分析和平均情況複雜度分析,下面分別討論這兩個問題。

1.3.2 最壞情況時間複雜度分析

由於演算法可以接受不同的輸入,所以它的複雜度對於不同輸入一般是不一樣的。對於輸入而言,它的乙個核心的屬性是其規模,這很大程度上決定了演算法複雜度的高低。所以演算法分析的本質不是具體的乙個複雜度的值,而是輸入規模n到演算法複雜度的乙個函式關係f(n)。

不過進一步分析,上述思路中有乙個小的漏洞:即使對於同樣的輸入規模,演算法的執行時間也可能不同。所以同樣的問題規模n可能有多個代價值與之相對應,也就是問題規模到演算法複雜度的對映並不是乙個函式對映。為此,我們引入演算法的最壞情況複雜度的概念,其含義是在給定的規模下,最壞的輸入所對應的演算法複雜度。因為對於給定的問題規模n,其最高代價是確定的,所以我們就建立了問題規模n與最壞情況複雜度w(n)之間的函式關係。最壞情況複雜度不僅僅是數學上的乙個函式關係,它同樣有比較直觀的現實意義。當我們能夠接受乙個演算法的最壞情況複雜度時,我們就可以在任何情況下確保安全地使用該演算法。

我們可以嚴格地定義w(n)如下。當問題輸入規模為n時,演算法所有可能的合法輸入集合記為dn,乙個具體的演算法輸入例項記為i,f(i)表示對於具體的輸入例項i演算法的時間複雜度,則演算法最壞情況時間複雜度可以定義為:w(n)=maxi∈dn f(i)這裡主要討論最壞情況時間複雜度,最壞情況空間複雜度的定義是類似的。

我們通過乙個具體的例子來展示演算法的最壞情況時間複雜度分析。假設需要在陣列a[1..n]中查詢輸入的元素e。為了簡化後續分析,假設e必然存在於陣列a[1..n]中,且僅出現1次。我們提出乙個基於遍歷所有輸入元素的演算法來解決這一問題,其實現如演算法2所示。演算法2:sequential-search(a[1..n],e)

1 for i∶=1 to n do

2 if a[i]=e then

3 return i ;基於對輸入元素的假設,我們發現演算法2的代價主要取決於元素e出現於陣列中的位置。元素e的位置越靠後,演算法的代價越大。所以其最壞情況代價對應於e出現於a[n]位置時的代價n。所以演算法2的最壞情況時間複雜度w(n)=n。

1.3.3 平均情況時間複雜度分析

僅靠最壞情況時間複雜度尚不能充分表徵演算法的效能。一種經常出現的情況是,演算法在遇到某些輸入時代價很高,所以它的最壞情況時間複雜度很高。但是這些「壞輸入」出現的可能性很小,所以綜合來看這樣的演算法的效能是良好的。此時應該有乙個比最壞情況時間複雜度更「公平」的指標來度量演算法的代價。為此,我們引入平均情況時間複雜度的概念。

為了表徵不同輸入出現的可能性不同的情況,假設演算法所有可能的輸入服從某個概率分布,這樣演算法的時間複雜度就成為乙個隨機變數,而它的期望值a(n)就被定義為演算法的平均情況時間複雜度。記每個輸入i出現的概率為pr,則:a(n)=∑i∈dnpr・f(i)同樣考察上述元素查詢的問題。假設所有可能的輸入等概率地出現。由於元素e必然出現於陣列a[1..n]中的某乙個位置上,演算法的代價僅受元素e實際出現的位置影響。所有可能的輸入按照元素e出現位置的不同分為n種情況,分別對應於元素e出現在a[1],a[2],…,a[n]這n個位置上。分析這每種情況出現的概率及其對應的演算法代價,我們得出演算法的平均情況時間複雜度為:a(n)=∑ni=11n・i=n+121.4 習題

1.1 (3個數排序) 輸入3個各不相同的整數:

1) 請設計乙個演算法將輸入的3個整數排序。

2) 在最壞情況下、平均情況下你的演算法分別需要進行多少次比較?(假設所有可能的輸入等概率出現。)

3) 在最壞情況下將3個不同整數排序至少需要多少次比較?請證明你的結論。

1.2 (3個數的中位數) 輸入3個各不相同的整數:

1) 請設計乙個尋找3個數的中位數的演算法。

2) 在最壞情況下、平均情況下你的演算法分別需要進行多少次比較?(假設所有可能的輸入等概率出現。)

3) 在最壞情況下找出3個不同整數的中位數至少需要多少次比較?請證明你的結論。

1.3 (集合覆蓋問題) 定義集合的最小覆蓋如下:已知全集u=。給定u的子集組成的集合族s=,找出s的最小子集t,滿足∪si∈tsi=u。例如,全集u=有下面幾個子集,s1=,s2=,s3=和s4=,則最小覆蓋為。

1) 找出下面演算法失敗的例子:首先選擇s中最大的集合si,並從全集中將si中的所有元素刪除;然後從s中剩餘的集合中挑選最大的並從全集中刪除對應元素;重複上述過程直到全集中的所有元素都被覆蓋。

2) 請設計乙個演算法計算輸入全集的乙個集合覆蓋,並證明你所設計演算法的正確性。

3) 你所設計的演算法能否保證總是得出最小覆蓋?如果不能,請針對你的演算法設計乙個反例。

1.4 (換硬幣問題) 定義換硬幣問題如下:給定n個硬幣,它們的面值是正整數s=;另外給定乙個正整數金額值t。我們需要從s中找出若干個硬幣,使得它們的面值和為t,或者返回「不存在這樣的硬幣集合」。我們給出3種不同的演算法設計方案。

1) 依次掃瞄硬幣s1,s2,…,sn,並累加金額。

2) 按面值從小到大的順序依次掃瞄硬幣,並累加金額。

3) 按面值從大到小的順序依次掃瞄硬幣,並累加金額。

在上述掃瞄過程中,如果金額值累積到正好為t,則返回已經掃瞄到的硬幣;否則返回「不存在這樣的硬幣集合」。請將上述3種方案分別寫成演算法,並通過舉反例的方式證明這3個演算法的「不正確性」。

1.5 (多項式計算) horner演算法是用來計算多項式p(x)=anxn+an-1xn-1+…+a1x+a0的,請證明其正確性。1 algorithm: horner(a[0..n], x)

2 p ∶= a[n] ;/陣列a[0..n]存放係數a0,a1,…,an/

3 for i∶=n-1 downto 0 do

4 p∶=p・x+a[i] ;

5 return p ;1.6 (整數相乘) int-mult演算法用來計算兩個非負整數y、z的乘積。1 algorithm: int int-mult(int y, int z)

2 if z=0 then

3 return 0;

4 else

5 return int-multcy,zc + y・(z mod c);1) 令c=2,請證明演算法的正確性。

2) 令c為任意的乙個不小於2的常數,請證明演算法的正確性。

1.7 演算法的輸入r為1到n之間的正整數,r取不同值的概率如下:pr=1n1≤i≤n4

2nn412nn22 perform 10 operations ;

3 else if n44 perform 20 operations ;

5 else if n26 perform 30 operations ;

7 else

8 perform n operations ;

演算法設計與分析 作業13 讀書筆記

啊哈!演算法 讀書筆記 啊哈!演算法 這本書中的演算法舉例貼近生活,語言詼諧幽默,不會讓人產生枯燥感,並配有很多幽默的插圖。演算法講解通俗易懂,並配有詳細c語言 和注釋,是一本適合初學者學習以及借鑑的演算法書籍。由於時間有限,我簡單花了一些時間閱讀了其中的排序板塊,各種排序演算法層出不窮,一直都是困...

演算法分析與設計 作業13 讀書筆記

我在知乎上找有關演算法書的推薦,偶然間找到了這本 演算法導論 雖然我沒有完全看完,但我還是獲得了一些收穫。通過閱讀這本書使我更深刻地了解了演算法思想。我了解了書中有關動態規劃 貪心演算法 攤還分析 b樹 斐波那契堆等內容。初次接觸演算法,我感到還是有點困難,尤其是在演算法分析這一塊。一般來說學習演算...

演算法設計與分析 1 3 杰哥和數字

有乙個正整數x,想知道有多少個滿足要求的正整數d存在,要求是d是x的因子,並且d和x至少有一位相同。只有一行,乙個正整數x。對於30 的資料,x 100。對於50 的資料,x 200。對於100 的資料,x 1000000000。只有一行,乙個整數表示滿足要求的數字d的個數。102 順著題目思路,分...