AVL Tree

AVL树是一种保持平衡的二叉搜索树,最大节点高度差不超过1,以确保搜索效率为O(logn)。文章详细介绍了AVL树的概念、不平衡情况、四种旋转操作(单左旋RL、单右旋RR、双旋RR-RL和RL-RR)以及插入和删除节点后的平衡检查和调整策略。
摘要由CSDN通过智能技术生成

Goal

To avoid the binary tree becoming “a stick”, which makes the worst-case complexity of search Θ ( n ) \Theta(n) Θ(n).

Imbalance

The maximum difference of each node’s left and right subtree height.
Mathematical Representation:
For the tree T ( V , E ) T(V,E) T(V,E), its imbalance is defined as

m a x v ∈ V ∣ h e i g h t _ o f _ l e f t _ s u b t r e e ( v ) − h e i g h t _ o f _ r i g h t _ s u b t r e e ( v ) ∣ \underset{v\in V}{max}\left| height\_of\_left\_subtree(v) - height\_of\_right\_subtree(v) \right| vVmaxheight_of_left_subtree(v)height_of_right_subtree(v)

AVL Tree Definition

A binary tree with an imbalance not greater than 1.

Rotations

Operations to rebalance the binary tree.

Example:
        5                                5
       / \                              / \
      2   7                            3   7
       \                ---->         / \   
        3                            2   4
         \
          4
(Imbalance: 2)                     (Imbalance: 1)

Single Left Rotation (RL)

RL: Overview

// function call: RL(1)
    1                                    3
   / \                                  / \
  0   3                                /   \
     / \             ---->            1     5
    2   5                            / \   / \
       / \                          0   2 4   6
      4   6

RL: Breakdown

Step 1: root(1) gets its right child(3)'s left child(2) as its right child
// root->right = root->right->left;
// Remark: root->elt (1) <= root->right->elt (3)

    1                                    
   / \                                  
  0   3                                 1            3
     / \             ---->             / \          / \
    2   5                             0   2       (2)  5
       / \                                            / \
      4   6                                          4   6
      
// Remark: the (2) is still there, but logically it's disintegrated from 3.




Step 2: the original root(1) becomes the original right child(3)'s left child.
// original_right->left = root;
// CANNOT use root->right since it's overwritten!
// Remark: root->elt (1) <= root->right->elt (3)

    1            3                            3
   / \          / \                          / \
  0   2       (2)  5        ---->           /   \
                  / \                      1     5
                 4   6                    / \   / \
                                         0   2 4   6

.

Single right rotation (RR)

RR: Overview

// function call RR(5)
         5                                3
        / \                              / \
       3   6                            /   \
      / \               ---->          1     5
     1   4                            / \   / \        
    / \                              0   2 4   6
   0   2

RR: Breakdown

Step 1: root(5) gets its left child(3)'s right child(4) as its left child
// root->left = root->left->right;
// Remark: root->elt (5) >= root->left->right->elt (4)

         5                                
        / \                              
       3   6                          5              3
      / \               ---->        / \            / \
     1   4                          4   6          1  (4)
    / \                                           / \
   0   2                                         0   2
// Remark: the (4) is still there, but logically it's disintegrated from 3.



Step 2: the original root(5) becomes the original left child(3)'s right child
// original_left->right = root;
// CANNOT use root->left since it's overwritten!
// root->left->elt (3) <= root->elt (5)

     5              3                            3
    / \            / \                          / \
   4   6          1  (4)        ---->          /   \
                 / \                          1     5
                0   2                        / \   / \    
                                            0   2 4   6

Double Rotation (RR-RL)

RR-RL: Overview

// function call RR-RL(1)
    1                                    3
   / \                                  / \
  0   5                                /   \
     / \            ---->             1     5       
    3   6                            / \   / \
   / \                              0   2 4   6
  2   4

RR-RL: Breakdown

Step 1: RR(root->right)

    1                                1
   / \                              / \
  0   5                            0   3    
     / \            ---->             / \
    3   6                            2   5
   / \                                  / \
  2   4                                4   6



Step 2: RL(root)
    
    1                                    3
   / \                                  / \
  0   3                                /   \
     / \             ---->            1     5
    2   5                            / \   / \
       / \                          0   2 4   6
      4   6

Double Rotation (RL-RR)

RL-RR: Overview

// function call RL-RR(5)

        5                            3
       / \                          / \
      1   6                        /   \
     / \            ---->         1     5
    0   3                        / \   / \
       / \                      0   2 4   6
      2   4

RL-RR: Breakdown

Step 1: RL(root->left)

        5                            5
       / \                          / \
      1   6                        3   6
     / \            ---->         / \
    0   3                        1   4
       / \                      / \
      2   4                    0   2



Step 2: RR(root)

         5                                3
        / \                              / \
       3   6                            /   \
      / \               ---->          1     5
     1   4                            / \   / \        
    / \                              0   2 4   6
   0   2

Checking and Balancing

As insert finishes, each node along the insertion path should be checked recursively (i.e. starting from the leaf, ending at the root) for imbalance.

// bal(Node* n) := height(n->left) - height(n->right)

Algorithm checkAndBal (Node* n)
if bal(n) > 1;                // if imbalance > +1, at least an RR needed
    if bal(n->left) < 0       // double rotation needed if signs disagree
        rotateL(n->left);
    rotateR(n);
else if bal(n) < -1           // if imbalance < -1, at least an RR needed
    if bal(n->right) > 0      // double rotation needed if signs disagree
        rotateR(n->right);
    rotateL(n);
                              // nothing to be done if -1 <= imbalance <= 1

Remove in an AVL Tree

  • Remove as in a binary search tree
  • Rebalance if an imbalance has been created

Review: remove in a binary search tree

  • Leaf node: replace with nullptr
  • Only has left child: replace with left child
  • Only has right child: replace with right child
  • Has both left and right children:
    • Replace with in-order successor
    • Remove in-order successor from its original position
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值