平衡搜索树(一) AVL树

AVL树

AVL树又称为高度平衡的二叉搜索树,是1962年有俄罗斯的数学家G.M.Adel'son-Vel'skii和E.M.Landis提出来的。它能保持二叉树的高度 平衡,尽量降低二叉树的高度,减少树的平均搜索长度AVL树的性质

1. 左子树和右子树的高度之差的绝对值不超过1

2. 树中的每个左子树和右子树都是AVL树

3. 每个节点都有一个平衡因子(balance factor--bf),任一节点的平衡因子是-1,0,1。(每个节点的平衡因子等于右子树的高度减去左子 树的高度 )
AVL树的效率

一棵AVL树有N个节点,其高度可以保持在log2N,插入/删除/查找的时间复杂度也是log2N。

 

当出现不平衡的情况时的四种情况:

1.只需要右旋(汉子笔画为一“”),无论在黄(son)的左边插入还是右边插入,红(grandparent)的平衡因子,绿(parent)的平衡因子总能保持为0;

2.只需要左旋(汉子笔画为一“捺”)与情况1类似,此处就不再累赘;

 

3.左右旋(汉字笔画为一“”,一“”)

(1)绿的平衡因子为 0。有且只有一种可能;

(2)绿的平衡因子为-1。在绿(son)的左边插入,红(grandparent)的平衡因子为1,黄(parent)的平衡因子为0,绿(son)的平衡因子为0;

 

(3)绿的平衡因子为1。在绿(son)的右边插入,红(grandparent)的平衡因子为0,黄(parent)的平衡因子为-1,绿(son)的平衡因子为0;

4.右左旋(汉字笔画为一“捺”,一“撇”),情况与左右旋类似;

 

Now   图画完了~~  大体思想了解了   闲话就不多叙述了--直接上代码

 

//AVLTree 的节点类

 1 template<class K,class V>
 2 struct AVLTreeNode
 3 {
 4     typedef AVLTreeNode<K, V> Node;
 5     AVLTreeNode(const K& key, const V& value)
 6         :_left(NULL), _right(NULL), _parent(NULL)
 7         , _balance(0), _key(key), _value(value)
 8     {}
 9     
10     Node * _left;
11     Node * _right;
12     Node * _parent;
13     int _balance;
14     K _key;
15     V _value;
16 };

 

 

//AVLTree    (这个就是AVLTree  的类)

 1 template<class K,class V>
 2 class AVLTree
 3 {
 4     typedef AVLTreeNode<K, V> Node;
 5 public:
 6     AVLTree()
 7         :_root(NULL)
 8     {}
 9 public:
10     //增加节点
11     bool _Push(const K& key, const V& value);    
12     void _LeftSpin(Node *& parent);
13     void _RightSpin(Node * & parent);
14     void _LeftRightSpin(Node *& _RightSpinparent);
15     void _RightLeftSpin(Node *& parent);
16     
17     //查找结点
18     Node* _Find(const K& key);
19 
20     //修改节点
21     bool _Change(const K& key,const V& value);
22 
23     //检测
24     void _LevelOrder();
25     void _InOrder(){ InOrder(_root); }
26     int _Depth(){ Depth(_root); }
27     void InOrder(Node * root);
28     int Depth(Node * root);
29 protected:
30     Node * _root;
31 };

 

 

//AVLTree的构建   

 1 //增加节点
 2 template<class K,class V>
 3 bool AVLTree<K, V>::_Push(const K& key, const V& value)
 4 {
 5     if (_root == NULL)
 6     {
 7         _root = new Node(key, value);
 8         return true;
 9     }
10     else           //如果要根节点不为空
11     {
12         Node * insert = new Node(key, value);
13         Node * cur = _root;
14         Node * parent = NULL;
15         while (cur)          //找插入的位置
16         {
17             parent = cur;
18             if (key > cur->_key)
19             {
20                 cur = cur->_right;
21             }
22             else if (key < cur->_key)
23             {
24                 cur = cur->_left;
25             }
26             else
27             {
28                 return false;
29             }
30         }
31         if (key > parent->_key)      //将该节点插入到parent的右边
32         {
33             parent->_right = insert;
34             insert->_parent = parent;
35         }
36         else                        //将该节点插入到parent的左边
37         {
38             parent->_left = insert;
39             insert->_parent = parent;
40         }
41         cur = insert;               //cur指向新插入的节点
42 while (parent) //向上调节平衡因子 43 { 44 if (cur->_key > parent->_key) 45 { 46 parent->_balance++; 47 } 48 else 49 { 50 parent->_balance--; 51 } 52 if (parent->_balance == 0 || parent->_balance == 2 || parent->_balance == -2) //当_balance == 0 说明已经平衡了。_balance == 2 || _balance == -2 说明需要调整了
53 { 54 break; 55 } 56 cur = parent; 57 parent = cur->_parent; 58 } 59 60 if (parent && (parent->_balance == 2 || parent->_balance == -2)) //如果_balance == 2 || _balance == -2 61 { 62 if (parent->_balance == 2) 63 { 64 if (cur->_balance == 1) 65 { 66 _LeftSpin(parent); //上面的情况2 67 } 68 else 69 { 70 _RightLeftSpin(parent); //上面的情况472 } 73 } 74 else if(parent->_balance == -2) 75 { 76 if (cur->_balance == -1) 77 { 78 _RightSpin(parent);     //上面的情况1
79 } 80 else 81 { 82 _LeftRightSpin(parent); //上面的情况384 } 85 } 87 } 88 return true; 89 } 90 }

 

 

//左旋(按照上面的来敲带码,其实是很简单滴)

 1 template<class K, class V>
 2 void AVLTree<K, V>::_LeftSpin(Node *& parent)
 3 {
 4     Node* son = parent->_right;
 5     Node* grandparent = parent->_parent;
 6 
 7     parent->_right = son->_left;
 8     if (son->_left)
 9     {
10         son->_left->_parent = parent;
11     }
12     son->_left = parent;
13     parent->_parent = son;
14 
15     son->_parent = grandparent;
16     if (grandparent)
17     {
18         if (parent->_key > grandparent->_key)
19         {
20             grandparent->_right = son;
21         }
22         else
23         {
24             grandparent->_left = son;      
25         }
26     }
27 
28     parent->_balance = 0;       //将平衡因子置为零
29     son->_balance = 0;
30 
31     if (_root == parent)
32     {
33         _root = son;
34     }
35     parent = son;
36 }

 

 

//左右旋

template<class K, class V>
void AVLTree<K, V>::_LeftRightSpin(Node *& parent)
{ Node
* son = parent->_left; bool left = false; bool right = false; if (son->_right->_balance == -1) //如图,如果son 的 balance == -1 调整好后 grandparent 的 平衡因子为 1;即 (当前parent->right == 1);
    {
        left = true;
    }
    else if (son->_right->_balance == 1)      //如图,如果 son 的 balance == 1  调整好后  parent 的 平衡因子为 -1;即(当前parent->left == -1);
    {
        right = true;
    }
    _LeftSpin(son);   //(这里有一个坑:参数传的是引用,所以实参不能传(grandparent->_left)否则就会有神奇的事情发生^_^  ~~ 这里要小心再小心!!!前车之鉴呀大兄弟)
  _RightSpin(parent); if (left) { parent->_right->_balance = 1; } else if (right) { parent->_left->_balance = -1; } }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2016-04-27 12:16  in_the_way  阅读(427)  评论(0编辑  收藏  举报