標籤:
先通過表的擴增這一例子來引入今天的主題——平攤分析和勢能分析
一個雜湊表的大小應該為多少比較合適?
theta(n)比較合適
可是萬一我們不知道n是多大呢
使用動態表解決 溢出就建立一個大小翻倍的空間,然後複製過去
這樣做插入的最壞時間複雜度為n
讓我們看看平均的時間複雜度,每次基本插入操作為1,空間溢出時需要開一個更大一倍的空間,並複製當前的元素過去,所以空間溢出時所需要的時間為2的i次方(i為第幾次溢出)
所以其真實的時間消耗為n+sigma(2^i) 0<=i<=lg(n+1) 即3n
因此其實插入的時間複雜度為O(1)
儘管有時會有巨大開銷,但是會被平均的開銷平攤掉,這就是平攤分析
平攤分析:平均操作複雜度不高,儘管有些操作會有較高的複雜度
三種類型的平攤方法:
1.聚集分析
2.記賬方法(accounting)
3.勢能分析
2.3它們為每一個操作分配了特點的平攤代價
記賬方法:
想象自己擔任了一個會記
對第i個操作收費為ci
收益個虛構的平攤代價
每一步運算需要花費1$
未用到的餘款就被存到銀行,用於償付以後的操作
如每次插入收費為3,插入消耗1,剩下的2存入銀行為表翻倍時做準備,要始終保證銀行的金額為正
即提前平攤,總能支付擴充表的費用,這樣某一個高開銷的操作會被平攤掉
勢能方法:
演算法分析裡最漂亮的產物之一
剛開始資料結構狀態為D0
操作i的代價為ci
操作i可以看作把資料結構由Di-1轉化為Di
定義勢能函數
將資料結構的集合定位實數值
D0 = 0 初始的勢為0
所有Di >=0,我們不能讓勢低於0
定義平攤代價為Ai,對勢能Di有Ai=Ci+Di-Di-1
Di-Di-1 部分是勢能的改變數,如果其>=0 那麼Ai>ci 我收取的費用超過了實際的花費,即操作i儲存了後面資料結構所需的功
如果勢能的改變數<0,即我們用儲存的勢能轉化為能量來協助完成操作i
記賬方法考慮的是平攤代價
而勢能分析考慮的是銀行存款(儲存勢能)
有sigmaAi=sigma(ci+Di-Di-1)=sigma(ci+Dn-D0)
D0為0,Dn大於等於0,所以左邊大於右邊,是實際代價的一個上界
我們再次以表的擴增為例感受一下勢能分析
我們的勢能函數為2i-2^ceil(lgi)
如何推匯出這樣的勢能函數的?
定義勢能函數難度低於定義平攤代價
Di>=0
第i個操作的平攤代價Ai=Ci+Di-Di-1= i+2i-2^ceil(lgi)-(2i-2-2^ceil(lgi-1))(剛好i是2的冪)
1+2i-2^ceil(lgi)-(2i-2-2^ceil(lgi-1))
case1 i-1是2的冪,那麼Ai=i+2-2(i-1)+(i-1)=3
case2 i-1不是2的冪 那麼Ai=1+2i-2^ceil(lgi)-(2i-2-2^ceil(lgi-1))=3
這樣得到的平攤代價也為3
不關注即時效能只關注聚集效能
【演算法導論】 第十三課 平攤分析、表的擴增、勢能分析