1. 程式人生 > >演算法導論學習筆記之攤還分析

演算法導論學習筆記之攤還分析

攤還分析中,我們求資料結構的一個操作序列中所執行的所有操作的平均時間,來評價操作的代價。這樣,就可以說明即使一個序列的某個操作很複雜,平均代價還是很低的。

攤還分析中最常用三種技術:

 聚合分析,這種方法用來確定一個n個操作的序列的總代價的上界T(n),因而每個操作的代價是T(n)/n,將平均代價作為每個操作的攤還代價

核算法,將某些較早操作的“餘額”作為“預付信用”儲存起來,與資料結構中的特定物件相關聯,在操作序列的隨後部分,儲存的信用即課為那些繳費少於實際代價的操作支付差額

勢能法,也是分析每個操作的攤還代價,也是通過較早操作的餘額來補償稍後操作的餘額的差額,但是不是針對物件的,而是將勢能作為整體儲存

好吧,這樣說起來很抽象,通過一個棧操作的例子來說明

普通的棧操作包括PUSH和 POP, 時間複雜性均是O(1),這裡加一個額外的MULTIPOP(S,k)操作,刪除棧S的從棧頂開始的k個元素(棧不空的情況下),這個操作的總代價是min(s,k)(退不到K個就棧空了,那就只退s個)。

聚合分析

一個由n個PUSH POP MULTIPOP組合的操作序列在一個空棧上的執行情況,序列中一個MULTIPOP操作的最壞情況代價的O(n),因為棧的大小最大為n,因此一個棧操作的最壞情況是O(n),從而n個操作的最壞情況是O(n2)。但是這不是一個確界。通過使用聚合分析,我們知道其實在一個空棧上進行一系列N個操作最多代價是O(n),因為當一個物件壓入棧後,最多將其彈出一次,因此對一個棧來說,能執行的POP次數,包括MULTIPOP中POP次數,都只能最多是PUSH的次數,所以上限其實是O(n)

核算法

對不同操作賦予不同費用,將這個費用稱為其攤還代價。當一個操作的攤還代價大於其實際代價時,將差額存入資料結構中的特定物件,存入的差額稱為信用。當然要確保信用是非負值,否則總體的攤還代價就會小於實際代價,求的就不是上界了。還是用上面的棧操作為例:

操作的實際代價是:

PUSH1

POP 1

MULTIPOP min(s,k)  s是呼叫棧的規模,k是引數

賦予這些操作如下攤還代價

PUSH2

POP0

MULTIPOP 0

在此例中,所有攤還代價都是常數。假定使用一美元表示一個單位的代價,從一個空棧開始,存入一個數據就相當於給出了代價2,但是實際只用話費1美元,那麼剩下的一美元就存起來,等到出棧的時候,這一美元正好用來當出棧的代價,相當於之前的兩美元是用來支付了入棧的代價同時預付了出棧的代價,所以在POP的時候可以不繳納任何費用,MULTIPOP也是一樣的。換句話說,每個數在入棧的時候都是已經有了一美元的出棧費,所以出棧相關的操作無需在繳納了。

勢能法

勢能法攤還分析並不將預付代價表示為資料結構中特定物件的信用(數的出棧費),而是表示為勢能或簡稱勢。

我們將對一個數據結構D0執行n個操作(比如棧),對每個i = 1,2,。。。n, ci為第i個操作的實際代價,令Di為在一個數據結構Di-1上執行第i個操作得到的結果資料結構。勢函式F將每個資料結構Di對映到一個實數F(i)(感覺就像物理上每個位置對應一個重力勢能一樣),那麼第i個曹組的攤還代價Ci = ci + F(Di)-F(Di-1),也就是攤還代價等於實際代價加上勢能差,所以總攤還代價就是 總實際代價+F(Dn)-F(D0) (是不是就像重力作用下勢能變化,只跟起始位置和初始位置的勢能值有關?)

再次回到上面的棧操作, 設F(D0) = 0,因為棧中物件永遠不可能為負,因此F(Di)>=0=F(D0).

如果第i個操作是PUSH操作,此時包含s個物件,則 F(Di)-F(Di-1)=(s+1)-s = 1

所以PUSH操作的攤還代價是Ci= ci + F(Di)-F(Di-1) = 2; 類似的POP的代價是0