小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

數(shù)據(jù)結(jié)構(gòu)九:AVL樹(O(logn))

 慢慢體驗(yàn)人生 2011-10-29

AVL樹

來(lái)自"NOCOW"

跳轉(zhuǎn)到: 導(dǎo)航, 搜索

本文在GNU自由文檔許可證之條款下提供

計(jì)算機(jī)科學(xué)中,AVL樹是最先發(fā)明的自平衡二叉查找樹。在AVL樹中任何節(jié)點(diǎn)的兩個(gè)兒子子樹的高度最大差別為一,所以它也被稱為高度平衡樹。查找、插入和刪除在平均和最壞情況下都是O(log n)。增加和刪除可能需要通過(guò)一次或多次樹旋轉(zhuǎn)來(lái)重新平衡這個(gè)樹。AVL樹得名于它的發(fā)明者 G.M. Adelson-VelskyE.M. Landis,他們?cè)?962年的論文 "An algorithm for the organization of information" 中發(fā)表了它。

節(jié)點(diǎn)的平衡因子是它的右子樹的高度減去它的左子樹的高度。帶有平衡因子 1、0 或 -1 的節(jié)點(diǎn)被認(rèn)為是平衡的。帶有平衡因子 -2 或 2 的節(jié)點(diǎn)被認(rèn)為是不平衡的,并需要重新平衡這個(gè)樹。平衡因子可以直接存儲(chǔ)在每個(gè)節(jié)點(diǎn)中,或從可能存儲(chǔ)在節(jié)點(diǎn)中的子樹高度計(jì)算出來(lái)。


目錄

[隱藏]

[編輯] 操作

AVL樹的基本操作一般涉及運(yùn)做同在不平衡的二叉查找樹所運(yùn)做的同樣的算法。但是要進(jìn)行預(yù)先或隨后做一次或多次所謂的"AVL 旋轉(zhuǎn)"。

假設(shè)由于在二叉排序樹上插入結(jié)點(diǎn)而失去平衡的最小子樹根結(jié)點(diǎn)的指針為a(即a是離插入點(diǎn)最近,且平衡因子絕對(duì)值超過(guò)1的祖先結(jié)點(diǎn)),則失去平衡后進(jìn)行進(jìn)行的規(guī)律可歸納為下列四種情況:

  1. 單向右旋平衡處理RR:由于在*a的左子樹根結(jié)點(diǎn)的左子樹上插入結(jié)點(diǎn),*a的平衡因子由1增至2,致使以*a為根的子樹失去平衡,則需進(jìn)行一次右旋轉(zhuǎn)操作;
  2. 單向左旋平衡處理LL:由于在*a的右子樹根結(jié)點(diǎn)的右子樹上插入結(jié)點(diǎn),*a的平衡因子由-1變?yōu)?2,致使以*a為根的子樹失去平衡,則需進(jìn)行一次左旋轉(zhuǎn)操作;
  3. 雙向旋轉(zhuǎn)(先左后右)平衡處理LR:由于在*a的左子樹根結(jié)點(diǎn)的右子樹上插入結(jié)點(diǎn),*a的平衡因子由1增至2,致使以*a為根的子樹失去平衡,則需進(jìn)行兩次旋轉(zhuǎn)(先左旋后右旋)操作。
  4. 雙向旋轉(zhuǎn)(先右后左)平衡處理RL:由于在*a的右子樹根結(jié)點(diǎn)的左子樹上插入結(jié)點(diǎn),*a的平衡因子由-1變?yōu)?2,致使以*a為根的子樹失去平衡,則需進(jìn)行兩次旋轉(zhuǎn)(先右旋后左旋)操作。

[編輯] 插入

向AVL樹插入可以通過(guò)如同它是未平衡的二叉查找樹一樣把給定的值插入樹中,接著自底向上向根節(jié)點(diǎn)折回,于在插入期間成為不平衡的所有節(jié)點(diǎn)上進(jìn)行旋轉(zhuǎn)來(lái)完成。因?yàn)檎刍氐礁?jié)點(diǎn)的路途上最多有 1.5 乘 log n 個(gè)節(jié)點(diǎn),而每次 AVL 旋轉(zhuǎn)都耗費(fèi)恒定的時(shí)間,插入處理在整體上耗費(fèi) O(log n) 時(shí)間。

在平衡的二叉排序樹Balanced BST上插入一個(gè)新的數(shù)據(jù)元素e的遞歸算法可描述如下:

  1. 若BBST為空樹,則插入一個(gè)數(shù)據(jù)元素為e的新結(jié)點(diǎn)作為BBST的根結(jié)點(diǎn),樹的深度增1;
  2. 若e的關(guān)鍵字和BBST的根結(jié)點(diǎn)的關(guān)鍵字相等,則不進(jìn)行;
  3. 若e的關(guān)鍵字小于BBST的根結(jié)點(diǎn)的關(guān)鍵字,而且在BBST的左子樹中不存在和e有相同關(guān)鍵字的結(jié)點(diǎn),則將e插入在BBST的左子樹上,并且當(dāng)插入之后的左子樹深度增加(+1)時(shí),分別就下列不同情況處理之:
    1. BBST的根結(jié)點(diǎn)的平衡因子為-1(右子樹的深度大于左子樹的深度,則將根結(jié)點(diǎn)的平衡因子更改為0,BBST的深度不變;
    2. BBST的根結(jié)點(diǎn)的平衡因子為0(左、右子樹的深度相等):則將根結(jié)點(diǎn)的平衡因子更改為1,BBST的深度增1;
    3. BBST的根結(jié)點(diǎn)的平衡因子為1(左子樹的深度大于右子樹的深度):則若BBST的左子樹根結(jié)點(diǎn)的平衡因子為1:則需進(jìn)行單向右旋平衡處理,并且在右旋處理之后,將根結(jié)點(diǎn)和其右子樹根結(jié)點(diǎn)的平衡因子更改為0,樹的深度不變;
  4. 若e的關(guān)鍵字大于BBST的根結(jié)點(diǎn)的關(guān)鍵字,而且在BBST的右子樹中不存在和e有相同關(guān)鍵字的結(jié)點(diǎn),則將e插入在BBST的右子樹上,并且當(dāng)插入之后的右子樹深度增加(+1)時(shí),分別就不同情況處理之。

[編輯] 刪除

從AVL樹中刪除可以通過(guò)把要?jiǎng)h除的節(jié)點(diǎn)向下旋轉(zhuǎn)成一個(gè)葉子節(jié)點(diǎn),接著直接剪除這個(gè)葉子節(jié)點(diǎn)來(lái)完成。因?yàn)樵谛D(zhuǎn)成葉子節(jié)點(diǎn)期間最多有 log n個(gè)節(jié)點(diǎn)被旋轉(zhuǎn),而每次 AVL 旋轉(zhuǎn)耗費(fèi)恒定的時(shí)間,刪除處理在整體上耗費(fèi) O(log n) 時(shí)間。(感覺(jué)這樣處理之后,有可能這個(gè)樹就不一定還是AVL樹了,正確應(yīng)該在刪除的時(shí)候也像插入的時(shí)候一樣,需要旋轉(zhuǎn)調(diào)整的吧)

[編輯] 查找

在AVL樹中查找同在一般BST完全一樣的進(jìn)行,所以耗費(fèi) O(log n) 時(shí)間,因?yàn)锳VL樹總是保持平衡的。不需要特殊的準(zhǔn)備,樹的結(jié)構(gòu)不會(huì)由于查詢而改變。(這是與伸展樹查找相對(duì)立的,它會(huì)因?yàn)椴檎叶兏鼧浣Y(jié)構(gòu)。)

[編輯] 參考實(shí)現(xiàn)

[AVL C++ && 陳啟峰——PASCAL版]

[編輯] 使用高度替代平衡因子

在linux早期的內(nèi)核中,AVL樹便是用存儲(chǔ)高度來(lái)判別樹是否平衡的,這樣的好處是能直接的得到任一節(jié)點(diǎn)的高度,旋轉(zhuǎn)時(shí)的更新也更容易(參看下面的推算)。使用高度替代平衡因子的實(shí)現(xiàn):AVL C++ Alternative Height Based

[編輯] 平衡因子的推算

在AVL樹的旋轉(zhuǎn)過(guò)程中,平衡因子(高度)的改變可以通過(guò)旋轉(zhuǎn)的類型推算得到。下面的推算是從本人的code中摘取的注釋,其中:

* bf(N) 節(jié)點(diǎn)N的平衡因子(balance factor)
* h(N)  節(jié)點(diǎn)N的高度    (height) 
* No    旋轉(zhuǎn)前的節(jié)點(diǎn)N  (old node)
* Nn    旋轉(zhuǎn)后的節(jié)點(diǎn)N  (new node)
* 高度和平衡因子保持不變的節(jié)點(diǎn)用數(shù)字 1, 2, 3...表示

/* LL: right rotate

*  
*       (N)                (L)
*      /   \              /   *    (L)    3    ==>     1    (N)  
*   /   \                    /   *  1     2                  2     3
*
*
* how to get bf(Nn) ? 
*
* bf(No) = h(Lo)-h(3)
* bf(Nn) = h(2)-h(3)
* bf(No)-bf(Nn) = h(Lo)-h(2)
*               = max(h(1), h(2))+1-h(2)
*               = max(h(1)-h(2), 0)+1
*               = max(bf(Lo), 0)+1
*
* bf(Nn) = bf(No)-(max(bf(Lo), 0)+1)
*
* Result:
*
* bf(N) -= max(bf(bf(Lo), 0)+1
*
* how to get bf(Ln) ?
* 
* bf(Lo) = h(1)-h(2)
* bf(Ln) = h(1)-h(Nn)
* bf(Ln)-bf(Lo) = h(2)-h(Nn)
*               = h(2)-max(h(2), h(3))-1
*               = min(0, h(2)-h(3))-1
*               = min(0, bf(Nn))-1
*
* bf(Ln) = bf(Lo)+(min(0, bf(Nn))-1)
*
* Result:
*
* bf(L) += min(0, bf(Nn))-1
*
* how to get height ?
*
* h(Nn) = max(h(2), h(3))+1
* h(Ln) = max(h(1), h(Nn))+1
*
*/

/* RR: left rotate

*
*    (N)                (R)
*   /   \              /   *  1    (R)    ==>   (N)    3
*      /   \        /   *     2     3      1     2
*
*
* how to get bf(Nn) ? 
*
* bf(No) = h(1)-h(Ro)
* bf(Nn) = h(1)-h(2)
* bf(No)-bf(Nn) = h(2)-h(Ro)
*               = h(2)-max(h(2), h(3))-1
*               = min(0, h(2)-h(3))-1
*               = min(0, bf(Ro))-1
*
* bf(Nn) = bf(No)-(min(0, bf(Ro))-1)
*
* Result:
*
* bf(N) -= min(0, bf(Ro))-1
*
* how to get bf(Rn) ?
* 
* bf(Ro) = h(2)-h(3)
* bf(Rn) = h(Nn)-h(3)
* bf(Rn)-bf(Ro) = h(Nn)-h(2)
*               = max(h(1), h(2))+1-h(2)
*               = max(h(1)-h(2), 0)+1
*               = max(bf(Nn), 0)+1
*
* bf(Rn) = bf(Ro)+(max(bf(Nn), 0)+1)
*
* Result:
* 
* bf(R) += max(bf(Nn), 0)+1
*
* how to get height ?
* 
* h(Nn) = max(h(1), h(2))+1
* h(Rn) = max(h(Nn), h(3))+1
*
*/

/* LR: left-right rotate

* 
*          (N)                (LR)
*         /   \               /   *       (L)    4   ==>      (L)   (N)  
*      / \                  / \   / *     1  (LR)              1   2 3   4
*        / *       2   3
*
*  note that left-right rotate could be implemented as a call to 
*  left_rotate(L) followed by a call to right_rotate(N).
*
* how to get bf(Ln) ?
* 
* bf(Lo) = h(1)-h(LRo)
* bf(Ln) = h(1)-h(2)
* bf(Lo)-bf(Ln) = h(2)-h(LRo)
*               = h(2)-max(h(2), h(3))-1
*               = min(0, h(2)-h(3))-1
*               = min(0, bf(LRo))-1
*
* bf(Ln) = bf(Lo)-(min(0, bf(LRo))-1)
*
* Result:
* 
* bf(L) -= min(0, bf(LRo))-1
*
* how to get bf(Nn) ? 
*
* bf(No) = h(Lo)-h(4)
* bf(Nn) = h(3)-h(4)
* bf(No)-bf(Nn) = h(Lo)-h(3)
*               = max(h(1), max(h(2), h(3))+1)+1-h(3)
*               = max(h(1)-h(3), max(h(2)-h(3), 0)+1)+1
*               = max(h(1)-h(3), max(bf(LRo), 0)+1)+1
* bf(Ln) = h(1)-h(2)
* bf(LRo) = h(2)-h(3)
* h(1)-h(3) = bf(Ln)+bf(LRo)
*
* bf(Nn) = bf(No)-(max(bf(Ln)+bf(LRo), max(bf(LRo), 0)+1)+1)
*
* Result:
* 
* bf(N) -= max(bf(Ln)+bf(LRo), max(bf(LRo), 0)+1)+1
*
* how to get bf(LRn) ? 
*
* bf(LRo) = h(2)-h(3)
* bf(LRn) = h(Ln)-h(Nn)
* bf(LRn)-bf(LRo) = h(Ln)-h(2)+h(3)-h(Nn)
*               = max(h(1), h(2))+1-h(2)+h(3)-max(h(3), h(4))-1
*               = max(h(1)-h(2), 0)+min(0, h(3)-h(4))
*               = max(bf(Ln), 0)+min(0, bf(Nn))
*
* bf(LRn) = bf(LRo)+(max(bf(Ln), 0)+min(0, bf(Nn)))
*
* Result:
* 
* bf(LR) += max(bf(Ln), 0)+min(0, bf(Nn))
*
*/

/* right-left rotate

* 
*          (N)                  (RL)
*         /   \                 /   *        1     (R)     ==>    (N)   (R)  
*             /  \            / \   / *           (RL)  4          1   2 3   4
*           / *          2   3
*
*  note that right-left rotate could be implemented as a call to 
*  right_rotate(R) followed by a call to left_rotate(N).
*
* how to get bf(Rn) ?
* 
* bf(Ro) = h(RLo)-h(4)
* bf(Rn) = h(3)-h(4)
* bf(Ro)-bf(Rn) = h(RLo)-h(3)
*               = max(h(2), h(3))+1-h(3)
*               = max(h(2)-h(3), 0)+1
*               = max(bf(RLo), 0)+1
*
* bf(Rn) = bf(Ro)-(max(bf(LRo), 0)+1)
*
* Result:
* 
* bf(R) -= max(bf(LRo), 0)+1
*
* how to get bf(Nn) ? 
*
* bf(No) = h(1)-h(Ro)
* bf(Nn) = h(1)-h(2)
* bf(No)-bf(Nn) = h(2)-h(Ro)
*               = h(2)-max(max(h(2), h(3))+1, h(4))-1
*               = min(h(2)-max(h(2), h(3))-1, h(2)-h(4))-1
*               = min(min(0, h(2)-h(3))-1, h(2)-h(4))-1
*               = min(min(0, bf(RLo))-1, h(2)-h(4))-1
* bf(Rn) = h(3)-h(4)
* bf(RLo) = h(2)-h(3)
* h(2)-h(4) = bf(Rn)+bf(RLo)
*
* bf(Nn) = bf(No)-(min(min(0, bf(RLo))-1, bf(Rn)+bf(RLo))-1)
*
* Result:
* 
* bf(N) -= min(bf(Rn)+bf(RLo), min(bf(RLo), 0)-1)-1
*
* how to get bf(RLn) ?
*
* bf(RLo) = h(2)-h(3)
* bf(RLn) = h(Nn)-h(Rn)
* bf(RLn)-bf(RLo) = h(Nn)-h(2)+h(3)-h(Rn)
*               = max(h(1), h(2))+1-h(2)+h(3)-max(h(3), h(4))-1
*               = max(h(1)-h(2), 0)+min(0, h(3)-h(4))
*               = max(bf(Nn), 0)+min(0, bf(Rn))
*
* bf(RLn) = bf(RLo)+(max(bf(Nn), 0)+min(0, bf(Rn)))
*
* Result:
* 
* bf(RL) += max(bf(Nn), 0)+min(0, bf(Rn))
*
*/

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多