攤還分析 1 演算法導論 23

2022-02-10 17:53:58 字數 4429 閱讀 5968

攤還分析(amortized analysis)是一種分析乙個操作序列中所執行的所有操作的平均時間分析方法。與一般的平均分析方法不同的是,它不涉及概率的分析,可以保證最壞情況下每個操作的平均效能。

下面介紹癱瘓分析中的最常用的三種技術。

先來看對棧進行操作的例子。

通常,棧能夠進行push(s, x)pop(s)操作,其時間複雜度均為o(1)。現在定義乙個新的操作multipop(s, k),它刪除棧s棧頂的k個元素(若不足k個,則全部彈出為止)。下面是操作multipop(s, k)的偽**:

while not stack-empty(s) and k > 0

pop(s)

k = k - 1

可以看出,multipop的時間代價為min(s, k),其中s是棧中元素的個數。

下面我們分析乙個由n個push、pop和multipop組成的操作在乙個空棧上的執**況。

簡單地,根據上面對multipop操作時間代價(min(s, k))的分析,我們很快得出,乙個multipop操作的最壞時間是o(n),因為棧的大小是n,因此n個操作的序列的最壞時間代價是\(o(n^2)\)。雖然這個結論是正確的,但是它卻不是乙個確界。

從另乙個角度考慮,pop操作的次數至多與push操作的次數相等,而push操作的次數至多為n次。因此乙個由n個push、pop和multipop組成的操作的時間代價最多為o(n),分攤到每乙個操作的時間代價就為o(n) / n = o(1)。

我們再來看二進位制計數器遞增的例子。

二進位制計數器是用乙個陣列來表示乙個數,即陣列每乙個槽充當二進位制數的乙個數字,陣列的第乙個槽為最低位。

其遞增演算法的思路是:首先將最低位記為當前位。判斷當前位是否為1,若是,則將該位置為0,當前位右移一位(進製操作);不斷重複以上過程直至當前位的值不為1或者當前位「溢位」。最後,如果沒有「溢位」,就將當前位的值置為1。

下面是python實現**:

def increment(num):

i = 0

while i < len(num) and num[i] == 1:

num[i] = 0

i += 1

if i < len(num):

num[i] = 1

假設這個陣列長度位k。根據上面的**,我們可以發現,increment操作的最壞時間代價是 o(k),這在所有位上都是1時發生。因此,我們可以粗略地做出判斷:對初值位0的計數器執行n個increment操作的時間代價位o(nk)。

和前面一樣,事實上,這個上界是不確切的。因為increment操作不會在連續執行n次時,每次都是最壞情況。事實上,我們可以確切地計算出其時間代價:

\[ \sum_^⌊\frac⌋ < n\sum_^ \frac< 2 n

\]因此,對於乙個初值為0的計數器,執行乙個n個increment操作的序列的最壞時間代價是o(n),分攤到每乙個操作的時間代價為o(1)。

在用核算法(accounting method)進行攤還分析時,我們對不同操作賦予不同的費用,它可能多於或少於其實際代價,我們稱其為攤還代價

當乙個操作的攤還代價超出其實際代價時,我們將差額存入資料結構的特定物件,存入的差額稱為信用。對於後續操作中攤還代價小於其實際代價的情況,信用可以用來支付差額。

回到棧操作的例子,其中各操作的實際代價為:

操作實際代價

push

1pop

1multipop

min(k, s)

我們為這些操作賦予如下的攤還代價:

操作攤還代價

push

2pop

0multipop

0在每次進行push操作時,我們花費2個單位的代價,1個單位用來支付其本身的實際代價,另1個單位可作為信用儲存;當對棧中的任何乙個元素進行pop(multipop也屬於pop)操作時,可用該元素在push時儲存的信用來支付差額。這樣就保證了在任何時刻的信用值是非負的

因此,總實際代價的上界為總攤還代價,即為o(n)。

這是因為\(\sum\limits_^c'_i \geq \sum\limits_^c_i\)在任何時刻都成立,其中\(c_i\)為第i個操作的真實代價,\(c_i'\)為其攤還代價。

同理,我們也可以用核算法來分析上述二進位制計數器遞增的例子。

因為increment操作的時間效率與當前陣列中為1的位數成正比,因此我們將翻轉的位數作為操作的代價。

對於一次置位操作(將該位值置為1的操作),我們設其攤還代價為2。在進行一次置位操作時,我們花1個單位的代價來支付其本身的實際代價,剩餘1單位作為信用,用來支付將來可能的復位操作(將該位值置為0的操作)的代價。這樣就保證了在任何時刻的信用值是非負的。這樣就保證了在任何時刻的信用值是非負的

因此,總實際代價的上界為總攤還代價。而在一次increment操作中,只進行一次置位操作,因此總攤還代價o(n)。

核算法不同,勢能分析並不是將預付代價表示為資料結構中特定物件的信用,而是表示為「勢能」,簡稱「勢」。釋放勢能即可用來支付未來操作代價。我們將勢能與整個資料結構而不是特定物件相關聯。

假設我們對乙個初始資料結構\(d_0\)執行n個操作。對每乙個\(i=1, 2,...,n\),用\(c_i\)表示第i個操作的實際代價,\(d_i\)表示在資料結構\(d_\)上執行第i個操作得到的結果資料結構。勢函式\(\theta\)將每個資料結構\(d_i\)對映到乙個實數\(\theta(d_i)\),此值即為關聯到資料結構\(d_i\)的勢;並且定義第i個操作的攤還代價\(c_i'\)為:

\[c_i' = c_i + \theta(d_i) - \theta(d_)

\]即每個操作的攤還代價為其實際代價與其引起的勢能變化的和

於是,\(n\)個操作的總代價為:

\[\sum_^n c_i' = \sum_^n(c_i + \theta(d_i) - \theta(d_)) = \sum_^nc_i + \theta(d_n) - \theta(d_0)

\]做乙個移項,變形得:

\[\sum_^n c_i' - \sum_^n c_i = \theta(d_n) - \theta(d_0)

\]如果我們能定義乙個勢函式\(\theta\),使得\(\theta(d_n) \geq \theta(d_0)\),則總攤還代價\(\sum_\limits^n c_i'\)給出了總實際代價\(\sum_\limits^n c_i\)的乙個上界。

由於我們不是總能知道要執行多少個操作,因此無法直接保證\(\theta(d_n) \geq \theta(d_0)\)。但是如果我們將勢函式的選擇條件變得嚴格,使得\(\theta(d_i) \geq \theta(d_0)\)對於所有的i都成立,那麼就可以保證。

我們再次回到棧操作的例子。這次我們採用勢能法來分析該問題。

對於勢函式的選取,我們選擇將棧對映到其內部元素個數的函式,即\(\theta(d_i)表示第\)

\(i\)次操作棧時,棧中元素的個數。對於初始的空棧,有\(\theta(d_0) = 0\);並且由於棧中元素不可能為負,因此\(\theta(d_i) \geq 0 = \theta(d_0)\)。

因此,以上\(\theta\)函式定義的n個操作的總攤還代價為總實際代價的乙個上界。

有了以上\(\theta\)函式的定義,我們便可以計算棧上各種操作的攤還代價。

對於push操作,其實際代價為1,其引起的勢能變化也為1,因此其攤還代價為2。

對於pop操作,同理可得其攤還代價為0。

對於一次multipop操作,它會將\(k' = \min(k, s)\)個物件彈出,即其實際代價為\(k'\);引起的勢差變化為\(-k\),因此其攤還代價也為0。

綜上,每個操作的攤還代價都為o(1),n個操作的總攤還代價為\(o(n)\),總實際代價最壞為\(o(n)\)。

同樣我們再用勢能法來分析二進位制計數器遞增的例子。

與上面相似,我們將\(\theta(d_i)\)表示為二進位制計數器中,位上是1的位數。顯然\(\theta(d_i) \geq \theta(d_0) = 0\)。因此,總攤還代價為總實際代價的乙個上界。

再分析總攤還代價。對於一次increment操作,其實際代價為\(k'\)次復位操作和1次置位操作,為\(k'+1\);其引起的勢差變化為\(-k'+1\),因此攤還代價為\((k'+1) + (-k' + 1) = 2\),\(n\)個操作的總攤還代價為\(o(n)\),因此總實際代價最壞為\(o(n)\)。

演算法導論第17章 攤還分析

在攤還分析中,我們求資料結構的乙個操作序列中所執行的所有操作的平均時間,來評價操作的代價,從而說明乙個操作的平均代價是很低的,即使序列中某一單一操作的代價很高,不涉及改了,但可以保證最壞情況下每個操作的平均時間。攤還分析中主要的三種方法 1 聚合分析 2 核算法 即記賬法 3 勢能法 1 聚合分析 ...

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

在攤還分析中,我們求資料結構的乙個操作序列中所執行的所有操作的平均時間,來評價操作的代價。這樣,就可以說明即使乙個序列的某個操作很複雜,平均代價還是很低的。攤還分析中最常用三種技術 聚合分析,這種方法用來確定乙個n個操作的序列的總代價的上界t n 因而每個操作的代價是t n n,將平均代價作為每個操...

《演算法導論》筆記(11) 攤還分析 部分習題

習題11.1 3 i為2的冪時代價為i,其餘代價為1,聚合分析 1 2 1 4 1 1 1 8.n,若n趨近無窮大,極限為3。每次操作攤還代價為3.習題11.2 2 核算法解上題。在i 2 1到第i 1次操作之間,每次操作實際代價1,信用2,經過i 2次之後,累積信用為i,第i個操作一次性付出代價i...