這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
#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`):對該結點的左兒子的左子樹進行了一次插入。

左邊為調整前得節點,我們可以看出k2的左右子樹已不再滿足AVL平衡條件,調整後的為右圖。
由於K2的左孩子已經變大了,所以應該降低K1的高度,把K1往上提,而K2相應也得往下降。k2下降在k1的右子樹(因為k1的左子樹增加了,所以不可能再把k2降到k1的左子樹上),Y變為K2的左子樹(如果Y變成K2的有子樹,那麼k2的本身沒有了左子樹,還降為右子樹,那麼就一減一加,左右失調,平衡因子變成2)。
情況2(`LR`):對該節點的左孩子進行了一次插入

先從最先失去平衡的節點開始分析,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`):

情況4(`RL`)

實現代碼:
---
---
## 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) {}