今天我們主要討論所謂的平攤分析(amortized analysis),它是用來分析一系列操作的平均所需要的代價。可能有人會問它利用概率論的知識,通過概率來求平均情況。答案是否定的,它並不涉及概率。在一些情況下平攤分析能夠很好的幫助我們分析我們程式的代價或者消耗。
這部分主要有三個內容,如圖所示:
聚合分析比較簡單。它就是執行n次操作的最壞情況(worst case)下時間為t(
n), 所以平均時間為t(
n)/n
. 接下來我們用乙個示例展示一下。
1.1 棧操作
我們都知道棧的push() 和pop() 操作的代價都是o(
1), 如果它們共同操作n次的話,真實時間(actual time)θ(
n).這時我們將其平均化則只有o(
1).核算法是針對不同的操作有不同的平攤分析,同時我們利用平攤代價作為整個操作的上界。而總平
攤代價=
總實際代
價+所存
儲的信用
(cre
dit)
且信用的定義是這樣的:當乙個操作的平攤代價超出其實際代價時,我們將差額存入資料結構中的特定物件,存入的差額就是信用[1]。同時我們用c^
i 表示平攤代價, 而用ci
表示實際代價,且我們認為信用不為負數,所以我們有這樣的關係∑i
=1nc
^i≥∑
i=1n
ci(2.1)
下面我們直接引入例子:
2.1 棧操作
push()操作平攤代價為2, 1個用來真實操作的代價,而另乙個1用來從當信用(credit), 而信用用來支付未來某些操作的真實代價(如pop()操作)。
pop()操作平攤代價為0
通過公式
2.1 的計算我們可以算出乙個先push()操作
p 次,後pop()操作
q次,且q+
p=n(
p≥q)
總的平攤時間:
∑i=1
nc^i
=2p信
用(cr
edit
s):(
p−q)
實際時間
:∑i=
1nci
=∑i=
1nc^
i−cr
edit
s=2p
−(p−
q)=p
+q=n
又因為:
p>q,
所以:n
/2≤p
≤nso
:n≤總
的平攤時
間≤2n
所以綜上總的平攤時間和實際時間都是o(n)
勢能法和我們上述描述的核算法不同的地方在於它針對的是整個資料結構,而不是特定的資料操作。它像我們高中學的物理勢能差不多,當勢能公升高,儲存的勢能可以用來為將來的操作進行付費從而勢能降低。對於最初的資料結構我們用d0
表示,而在第
i 次操作後的資料結構狀態為di
表示。
同時在這裡我們用c^
i 表示第
i 次操作的平攤代價, 用ci
表示第i
次操作的真實代價,而用φ(
di)表示第
i 次操作後的總的
勢能。 而至於每次的平攤代價為: c^
i=ci
+φ(d
i)−φ
(di−
1)(3.1)
所以我們的總的平攤代價為: ∑i
=1nc
^i=∑
i=1n
(ci+
φ(di
)−φ(
di−1
))=∑
i=1n
ci+φ
(dn)
−φ(d
0)(3.2)
我們將3.2 的公式變形可得實際代價: ∑i
=1nc
i=∑i
=1nc
^i−φ
(dn)
+φ(d
0)(3.3)
由於整個資料結構的勢能是不能為負的,且我們認為φ(
d0)=
0 , 所以很容易得: 總的
平攤代價
≥總的真
實代價也
就是:∑
i=1n
c^i≥
∑i=1
nci(3. 4)
下面我用例子詳細分析勢能法:
3.1棧操作pu
sh()
的真實代價為
1 ,且會增加
1個勢能 po
p() 的真實代價為
1 , 且會減少
1個勢能 現有p
個pus
h()操作和
q 個po
p()操作,且p+
q=n,
p≥q
w我們先利用公式
3.2 求其總的平攤代價: ∑i
=1nc
^i=∑
i=1p
(ci+
φ(di
)−φ(
di−1
))+∑
i=p+
1n(c
i+φ(
di)−
φ(di
−1))
=2p+
0=2p
(3.5)
可能會有人會問為什麼我們不用公式
3.2 的第
2 個公式來算,而只是用最原始的公式算?那是因為如果我們用第
2個公式,能解決許多問題的話,我們就不需要平攤分析了(因為我們利用平攤分析是來計算真實代價的,第2個式子的總的真實代價需要我們知道的)。這是因為在許多問題中, 每次的平攤代價很容易求, 而真實代價卻異常難。
在解釋一下:當0≤
i≤p 時,即每次的pu
sh()
操作的平攤代價為c^
i=1(
actu
alco
st)+
1(po
tent
ial)
=2;當p+1
≤i≤n
時,即每次的po
p() 操作的平攤代價為c^
i=1(
actu
alco
st)(
−1)(
pote
ntia
l)=0
e而第n次操作
後總的勢
能: φ
(dn)
=p−q
(3.6)
j將公式
3.5 和
3.6 代入到
3.3 中去得: ∑i
=1nc
i=2p
−(p−
q)=p
+q=n
所以n 次的pu
sh()
和pop
()操作的真實代價是o(
n), 也不難求出總平攤代價為o(
n).1)為什麼叫聚合分析(aggregate analysis)?
那是因為它把n操作的總代價加起來為f(
n), 而平攤到每次的操作則為f(
n)/n
. 2 )為什麼叫做核算法(the accounting method)?
首先我們考慮只有先有pu
sh()
操作,然後才會有po
p 操作, 所以我們把以後可能執行的po
p() 操作所需要的代價當做信用
(cre
dit)
儲存起來,當我們實際當中執行po
p() 操作時,我們就用我們預先的信用來支付就行了。
3 ) 為什麼叫是能法?
用上面最初的高中物理勢能知識理解。
4)核算法和勢能法都是將總的
平攤代價
作為真實
代價的最大上界
。當兩種方法都求解不真實的代價的話,我們只好還有乙個上界值得我們去考慮(往往這個上界對我們的程式分析往往很有用)。
[1] 《演算法導論》thomas h.cormen、charles e.leiserson等 第三版第17章 「攤還分析」 p261
平攤分析(Amortized Analysis)
平攤分析這一章,clrs的英文版一直沒有讀懂,不知道是不是心太浮了。今天把中文版的拿出來再讀一讀,希望愚鈍的頭腦能開一開竅。這一部分總標為高階分析技巧,想來也不是那麼好理解的,所以一遍不懂就再來一遍,百遍之內定能見其義了!在amortized analysis中,執行一系列資料結構操作 push,p...
平攤分析 演算法導論讀書筆記
我們經常會說乙個演算法快不快,這個可以由實驗得出,也可以通過分析複雜度得出。實驗需要大量不同的輸入才更全面準確,否則片面地看某個輸入下的表現,是比較偏頗的。分析複雜度 通常分析最壞,因為平均涉及輸入的概率分布,依靠假設或者實驗和經驗 有時候並不是乙個簡單的事,簡單的情況是遍歷 for int i 0...
二叉樹平攤
將一顆二叉樹平攤開來,如下 1 2 5 3 4 6 the flattened treeshould look like 1 2 3 4 5 6 思路 對每個節點,將左節點賦給右節點,同時用遞迴將左節點 flat 然後返回的 flat 的尾部,將右節點加在尾部的右節點上,並再用遞迴將其 flat 一...