avl樹 golang實現

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

#Tree


術語:
- 樹
- 根
- 節點
- 葉子
- 層次, 根節點
- 深度
- 樹的高度, 空樹的深度為`-1`, 根的深度為`0`, 一個節點的高度為`0`, 所有的樹葉的高度都為`0`。


---


##二叉樹
每個節點最多有兩個孩子,空樹也是一棵二叉樹,鏈表是一種特殊的二叉樹。


## 二叉排序樹(二叉搜尋樹,B樹)


## 滿二叉樹


## 完全二叉樹


## AVL樹
AVL樹本質上還是一棵二叉搜尋樹(因此讀者可以看到我後面的代碼是繼承自二叉搜尋樹的),它的特點是:


1. 本身首先是一棵二叉搜尋樹。 
2. 帶有平衡條件:每個結點的左右子樹的高度之差的絕對值(平衡因子)最多為1。 


例如:
```
     5              5
    / \            / \
   2   6          2   6
  / \   \        / \
 1   4   7      1   4
    /              /
   3              3
```
中,左邊的是AVL樹,而右邊的不是。因為左邊的樹的每個結點的左右子樹的高度之差的絕對值都最多為1,而右邊的樹由於結點6沒有子樹,導致根結點5的平衡因子為2。


假設有一個結點的平衡因子為2(在AVL樹中,最大就是2,因為結點是一個一個地插入到樹中的,一旦出現不平衡的狀態就會立即進行調整,因此平衡因子最大不可能超過2),那麼就需要進行調整。由於任意一個結點最多隻有兩個兒子,所以當高度不平衡時,只可能是以下四種情況造成的:


- 對該結點的左兒子的左子樹進行了一次插入(`LL`)。


- 對該結點的左兒子的右子樹進行了一次插入(`LR`)。


- 對該結點的右兒子的左子樹進行了一次插入(`RL`)。


- 對該結點的右兒子的右子樹進行了一次插入(`RR`)。


情況1和4是關於該點的鏡像對稱,同樣,情況2和3也是一對鏡像對稱。因此,理論上只有兩種情況,當然了,從編程的角度來看還是四種情況。


第一種情況是插入發生在“外邊”的情況(即左-左的情況或右-右的情況),該情況可以通過對樹的一次單旋轉來完成調整。第二種情況是插入發生在“內部”的情況(即左-右的情況或右-左的情況),該情況要通過稍微複雜些的雙旋轉來處理。




`旋轉:`


###單旋轉
情況1(`LL`):對該結點的左兒子的左子樹進行了一次插入。
![](http://blog.chinaunix.net/attachment/201108/14/25324849_1313308607C3xL.jpg)




左邊為調整前得節點,我們可以看出k2的左右子樹已不再滿足AVL平衡條件,調整後的為右圖。


由於K2的左孩子已經變大了,所以應該降低K1的高度,把K1往上提,而K2相應也得往下降。k2下降在k1的右子樹(因為k1的左子樹增加了,所以不可能再把k2降到k1的左子樹上),Y變為K2的左子樹(如果Y變成K2的有子樹,那麼k2的本身沒有了左子樹,還降為右子樹,那麼就一減一加,左右失調,平衡因子變成2)。


情況2(`LR`):對該節點的左孩子進行了一次插入
![](../../pic/2676FCA1-CF64-48B2-B4A7-73C41E8C16A7.png)


先從最先失去平衡的節點開始分析,B的left為h,right為h+2,失去平衡,c往上提,B往下提,以致降低整棵樹的高度(可以理解為`B,Bl,C,Cl,Cr`這顆樹,先把A ignore),C已經平衡,但是A失去平衡,C往上提,A往下降,以致降低整棵樹(`C,A,Ar`),Cr連到A的left防止A的right變大而失去平衡,最終C,B,A都已經平衡。


其實他們之間的方法都是一致的,高的節點往上提已經降低其高度,高的往下提,增加高度。這裡的***高度可以理解為樹的高度***, 他們採用的是一種策略,這是一種平衡左右子樹的`趨勢`


情況3(`RR`):


![](../../pic/7109344F-642A-4AC0-9F89-9B576FB59578.png)




情況4(`RL`)


![](../../pic/1CB097E6-D404-4CEC-8442-1DE3B3096A52.png)
實現代碼:


---
---


## B-樹,B+樹


---


---




package mainimport ("fmt")type DataType inttype Node AVLTreeNodetype AVLTree *AVLTreeNodetype AVLTreeNode struct {key   DataTypehigh  intleft  *AVLTreeNoderight *AVLTreeNode}func main() {data := []DataType{3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9}fmt.Println(data)var root AVLTree = nilfor _, value := range data {root = avl_insert(root, value)fmt.Println(" root -> key: ", root.key, "high :", root.high, "left", root.left, "right: ", root.right)  //  preorder(root)}preorder(root)fmt.Println()midorder(root)fmt.Println()}func highTree(p AVLTree) int {if p == nil {return -1} else {return p.high}}func max(a, b int) int {if a > b {return a} else {return b}}/*Please look LL*/func left_left_rotation(k AVLTree) AVLTree {var kl AVLTreekl = k.leftk.left = kl.rightkl.right = kk.high = max(highTree(k.left), highTree(k.right)) + 1kl.high = max(highTree(kl.left), k.high) + 1return kl}/*Please look RR*/func right_right_rotation(k AVLTree) AVLTree {var kr AVLTreekr = k.rightk.right = kr.leftkr.left = kk.high = max(highTree(k.left), highTree(k.right)) + 1kr.high = max(k.high, highTree(kr.right)) + 1return kr}/*so easy*/func left_righ_rotation(k AVLTree) AVLTree {k.left = right_right_rotation(k.left)return left_left_rotation(k)}func right_left_rotation(k AVLTree) AVLTree {k.right = left_left_rotation(k.right)return right_right_rotation(k)}func avl_insert(avl AVLTree, key DataType) AVLTree {if avl == nil {avl = new(AVLTreeNode)if avl == nil {fmt.Println("avl tree create error!")return nil}else {avl.key = keyavl.high = 0avl.left = nilavl.right = nil}} else if key < avl.key {avl.left = avl_insert(avl.left, key)if highTree(avl.left)-highTree(avl.right) == 2 {if key < avl.left.key { //LLavl = left_left_rotation(avl)} else { // LRavl = left_righ_rotation(avl)}}} else if key > avl.key {avl.right = avl_insert(avl.right, key)if (highTree(avl.right) - highTree(avl.left)) == 2 {if key < avl.right.key { // RLavl = right_left_rotation(avl)} else {fmt.Println("right right", key)avl = right_right_rotation(avl)}}} else if key == avl.key {fmt.Println("the key", key, "has existed!")}//notice: update high(may be this insert no rotation, so you should update high)avl.high = max(highTree(avl.left), highTree(avl.right)) + 1return avl}func preorder(avl AVLTree) {if avl != nil {fmt.Print(avl.key, "\t")preorder(avl.left)preorder(avl.right)}}func midorder(avl AVLTree) {if avl != nil {midorder(avl.left)fmt.Print(avl.key, "\t")midorder(avl.right)}}/*display avl tree*/func display(avl AVLTree) {}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.