平衡搜索樹—AVLTree

       AVL是平衡搜索二叉樹,它的主要特點在於:(1)左子樹和右子樹的高度差絕對值<1,(2)樹中的每個子樹都是AVL樹,(3)每個節點都有一個平衡因子(-1、0、1),平衡因子的大小等於右子樹的高度減左子樹的高度


      下面就是一個AVL樹:

650) this.width=650;" title="無標題.png" src="http://s5.51cto.com/wyfs02/M00/84/50/wKiom1eMsebCRlryAAAQLcWj2kc433.png" alt="wKiom1eMsebCRlryAAAQLcWj2kc433.png" />

其中,這個樹滿足左子樹和右子樹的高度差絕對值小於1,每個節點的平衡因子都滿足條件。


      下面是AVLTree中節點的結構:

template <class K, class V>
struct AVLTreeNode
{
     K _key;
     V _value;
     int _bf;     //節點的平衡因子
     AVLTreeNode<K, V>* _parent;     //指向節點的父節點
     AVLTreeNode<K, V>* _left;       //指向節點的左孩子
     AVLTreeNode<K, V>* _right;      //指向節點的右孩子
     
     AVLTreeNode(const K& key = K(), const V& value = V())    //構造節點
          :_key(key)
          , _value(value)
          , _parent(NULL)
          , _left(NULL)
          , _right(NULL)
          , _bf(0)
     { }
};


      下面討論一下AVLTree中插入節點的情況:

           當插入一個節點時,如果這個節點的父節點的平衡因子不滿足AVLTree的特點,這時就需要對AVLTree進行調整,直到滿足AVLTree的條件。


(1)左單旋


650) this.width=650;" width="619" height="301" title="無標題.png" style="width:618px;height:191px;" src="http://s1.51cto.com/wyfs02/M02/84/50/wKioL1eMtjjSxmwHAABedwoM0ho093.png" alt="wKioL1eMtjjSxmwHAABedwoM0ho093.png" />


(2)右單旋


650) this.width=650;" width="659" height="321" title="無標題.png" style="width:659px;height:220px;" src="http://s3.51cto.com/wyfs02/M01/84/51/wKiom1eMtuDRRoPAAABZx2YQJ0Y333.png" alt="wKiom1eMtuDRRoPAAABZx2YQJ0Y333.png" />


(3)左右雙旋


650) this.width=650;" width="659" height="397" title="無標題.png" style="width:659px;height:259px;" src="http://s3.51cto.com/wyfs02/M01/84/51/wKioL1eMt-ijMIeVAACQjP2m1GQ698.png" alt="wKioL1eMt-ijMIeVAACQjP2m1GQ698.png" />

(4)右左雙旋


650) this.width=650;" width="659" height="416" title="無標題.png" style="width:659px;height:274px;" src="http://s4.51cto.com/wyfs02/M01/84/51/wKiom1eMuNHRa4fGAACP_rAdDAA473.png" alt="wKiom1eMuNHRa4fGAACP_rAdDAA473.png" />


       針對上面的情況,下面是具體的程序實現:

#pragma once
#include <assert.h>
#include <math.h>
//實現平衡搜索二叉樹
//構造AVL樹的節點(使用三叉鏈表)

template <class K, class V>
struct AVLTreeNode
{
     K _key;
     V _value;
     int _bf;
     AVLTreeNode<K, V>* _parent;
     AVLTreeNode<K, V>* _left;
     AVLTreeNode<K, V>* _right;
     
     AVLTreeNode(const K& key = K(), const V& value = V())    //構造節點
          :_key(key)
          , _value(value)
          , _parent(NULL)
          , _left(NULL)
          , _right(NULL)
          , _bf(0)
     { }
};

template <class K, class V>
class AVLTree
{
     typedef AVLTreeNode<K, V> Node;
public:
     AVLTree()     //初始化根節點
          :_root(NULL)
     { }
     
     bool Insert(const K& key, const V& value)    //插入
     {
          //根節點判空
          if (_root == NULL)
          {
               _root = new Node(key, value);
               return true;
          }
          //將數據先插入到樹中
          Node* cur = _root;
          Node* parent = NULL;
          Node* tmp = new Node(key, value);
          while (cur)
          {
               if (cur->_key < key)
               {
                    parent = cur;
                    cur = cur->_right;
               }
               else if (cur->_key > key)
               {
                    parent = cur;
                    cur = cur->_left;
               }
               else
               {
                    return false;
               }
          }
          if (parent->_key > key)
          {
               parent->_left = tmp;
               tmp->_parent = parent;
          }
          if (parent->_key < key)
          {
               parent->_right = tmp;
               tmp->_parent = parent;
          }
          
          //對樹進行調整
          cur = tmp;
          parent = cur->_parent;
          bool isRotate = false;
          while (parent)
          {
               if (parent->_left == cur)     //插入左節點,父親節點的平衡因子-1
               {
                    parent->_bf--;
               }
               if (parent->_right == cur)   //插入右節點,父親節點的平衡因子+1
               {
                    parent->_bf++;
               }
               if (parent->_bf == 0)     
                //調整過程中,若碰到平衡因子爲0的節點,就不用在繼續調整
               {
                    break;
               }
               else if (parent->_bf == -1 || parent->_bf == 1)   //更新平衡因子
               {
                    cur = parent;
                    parent = cur->_parent;
               }
               else
               {
                    if (parent->_bf == 2)
                    {
                         if (cur->_bf == 1)      //左單旋
                         {
                              _RotateL(parent);
                         }
                         else       //右左單旋
                         {
                              _RotateRL(parent);
                         }
                    }
                    else           //=-2
                    {
                         if (cur->_bf == -1)      //右單旋
                         {
                              _RotateR(parent);
                         }
                         else                     //左右單旋
                         {
                              _RotateLR(parent);
                         }  
                    }
                    isRotate = true;
               }
               break;
          }
          
          if (isRotate)
          {
               if (parent->_parent == NULL)
               {
                    _root = parent;
                    return true;
               }
          }
          return true;
     }
     
     void InOrder()     //後序遍歷
     {
          _InOrder(_root);
          cout << endl;
     }
     
     bool IsBalance()
     {
          if (_root == NULL)
          {
               cout << "root is null!" << endl;
               return false;
          }
          return _IsBalance(_root);
     }
     
     int Heigth()
     {
          int heigthTree = 0;
          Node* cur = _root;
          while (cur)
          {
               if (cur != NULL)
               {
                    heigthTree++;
               }
               cur = cur->_left;
          }
          return _Heigth(_root, heigthTree, 0);
     }
    
protected:
     int _Heigth(Node* root, int heigthTree, int countNum)
     { 
          if (root == NULL)
          {
               if (countNum > heigthTree)
               {
                    heigthTree = countNum;
               }
               return heigthTree;
          }
          _Heigth(root->_left, heigthTree, countNum++);
          _Heigth(root->_right, heigthTree, countNum++);
     }
     
     bool _IsBalance(Node* root)
     {
          int bf = root->_right->_bf - root->_right->_bf;
          if (bf == 0 || bf == 1 || bf == -1)
          {
               return true;
          }
          else
          {
               return false;
          }
          _IsBalance(root->_left);
          _IsBalance(root->_right);
     }
    
     void _RotateL(Node*& parent)     //左單旋
     {
          Node* SubR = parent->_right;    //新建兩個節點指針
          Node* SubRL = SubR->_left;
          parent->_right = SubRL;        //進行調整
          if (SubRL)
          {
               SubRL->_parent = parent;
          }
          SubR->_left = parent;
          SubR->_parent = parent->_parent;
          parent->_parent = SubR;
          parent->_bf = SubR->_bf = 0;    //更改引用計數
          parent = SubR;
     }
     
     void _RotateR(Node*& parent)     //右單旋
     {
          Node* SubL = parent->_left;   //新建兩個節點指針
          Node* SubLR = SubL->_right;
          parent->_left = SubLR;    //進行調整
          if (SubLR)
          {
               SubLR->_parent = parent;
          }
          SubL->_right = parent;
          SubL->_parent = parent->_parent;
          parent->_parent = SubL;
          parent->_bf = SubL->_bf = 0;
          parent = SubL;
     }
     
     void _RotateRL(Node*& parent)     //右左單旋
     {
          Node* pNode = parent;
          Node* subRNode = parent->_right;
          Node* subRLNode = subRNode->_left;
          int bf = subRLNode->_bf;
          _RotateR(parent->_right);
          _RotateL(parent);
          if (bf == -1)
          {
               subRNode->_bf = 0;
               pNode->_bf = -1;
          }
          else if (bf == 1)
          {
               subRNode->_bf = 1;
               pNode->_bf = 0;
          }
          else
          {
               subRNode->_bf = 0;
               pNode->_bf = 0;
          }
          subRNode->_bf = 0;
     }
     
     void _RotateLR(Node*& parent)     //左右單旋
     {
          Node* pNode = parent;
          Node* subLNode = parent->_left;
          Node* subLRNode = subLNode->_right;
          int bf = subLRNode->_bf;
          _RotateL(parent->_left);
          _RotateR(parent);
          if (bf == -1)
          {
               subLNode->_bf = 0;
               pNode->_bf = 1;
          }
          else if (bf == 1)
          {
               subLNode->_bf = -1;
               pNode->_bf = 0;
          }
          else
          {
               subLNode->_bf = 0;
               pNode->_bf = 0;
          }
          subLNode->_bf = 0;
     }
     
     void _InOrder(Node* root)
     {
          if (root == NULL)
          {
               return;
          }
          _InOrder(root->_left);
          cout << root->_key << " ";
          _InOrder(root->_right);
     }
     
protected:
     Node* _root;
};

void Test()
{
     AVLTree<int, int> ht;
     /*ht.Insert(16, 1);
     ht.Insert(3, 1);
     ht.Insert(7, 1);
     ht.Insert(11, 1);
     ht.Insert(9, 1);
     ht.Insert(26, 1);
     ht.Insert(18, 1);
     ht.Insert(14, 1);
     ht.Insert(15, 1);*/
     
     ht.Insert(4, 1);
     ht.Insert(2, 1);
     ht.Insert(6, 1);
     ht.Insert(1, 1);
     ht.Insert(3, 1);
     ht.Insert(5, 1);
     ht.Insert(15, 1);
     ht.Insert(7, 1);
     ht.Insert(16, 1);
     ht.Insert(14, 1);
     
     ht.InOrder();
     cout<<ht.IsBalance()<<endl;
     cout << ht.Heigth() << endl;
}




本文出自 “無心的執着” 博客,請務必保留此出處http://10740590.blog.51cto.com/10730590/1827495

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章