• 查找(AVL平衡二叉树)


    【1】为什么需要平衡二叉树?

    矛盾是推进事物向前发展的源动力。

    那么平衡二叉树是从哪里来?肯定是有矛盾存在的。请看下面的分析:

    【2】什么是平衡二叉树?

    平衡二叉树的基本认识:

    【3】平衡二叉树的构建原理

    平衡二叉树的形成肯定是有一定规律可循的,那么平衡二叉树的“生长”原理是什么呢?

    请看程老师下面的构建示例以及详细讲解:

    关于平衡二叉树的旋转分为以下四种情况:

    【4】平衡二叉树的实现

    平衡二叉树的实现代码如下:

      1 #include <iostream>
      2 using namespace std;
      3 
      4 template<class Type> 
      5 class AVLtree;           
      6 
      7 template<class Type>
      8 class TNode
      9 {
     10     friend  class  AVLtree<Type>;
     11 private:
     12     Type  data;
     13     int   balance;    // 平衡因子
     14     TNode<Type> *leftChild, *rightChild;
     15 public:
     16     TNode(const Type &x =  Type(),TNode<Type> *left = NULL,TNode<Type> *right = NULL)
     17         : data(x)
     18         , leftChild(left)
     19         , rightChild(right)
     20         , balance(0)
     21     {}
     22 };
     23 
     24 template<class Type>
     25 class AVLtree
     26 {
     27 private:
     28     TNode<Type>  *root;
     29 private:
     30     void RightBalance(TNode<Type> * &r,bool  &action);
     31     void LeftBalance(TNode<Type> *&r,bool &action);
     32     void Insert(TNode<Type> * &root,const Type &x,bool &action);
     33     void LeftLeft(TNode<Type> * &r);
     34     void RightRight(TNode<Type> * &r);
     35     void LeftRight(TNode<Type> *&r);
     36     void RightLeft(TNode<Type> *&r);
     37     TNode<Type> *Parent(TNode<Type> *p,TNode<Type> *cur);
     38     TNode<Type> *FindNodeNext(TNode<Type> *cur);
     39     void DeleTNode(TNode<Type> *&cur,TNode<Type> *par);
     40     void Remove(TNode<Type> * &r,const Type &x,bool &action);
     41     void InOrder(TNode<Type> *p);
     42 public:
     43     AVLtree();
     44     void Insert(const Type &bt);
     45     TNode<Type> *Parent(TNode<Type> *cur);
     46     void Remove(const Type &x);
     47     void InOrder();
     48 };
     49 
     50 // 右平衡处理过程
     51 template<class Type>
     52 void AVLtree<Type>::RightBalance(TNode<Type> * &r, bool &action)
     53 {
     54     TNode<Type> *rightsub = r->rightChild, *leftsub = NULL;
     55     switch (rightsub->balance)   //判断右子树的平衡因子
     56     {
     57         case -1: // RR型
     58             r->balance = 0;
     59             rightsub->balance = 0;
     60             RightRight(r);   //RR型处理
     61             action = false;
     62             break;
     63         case 0:
     64             break;
     65         case 1: // RL型
     66             leftsub = rightsub->leftChild;  
     67             switch (leftsub->balance) // 判断左子树的平衡因子
     68             {
     69                 case 0: // RL型
     70                     r->balance = 0;
     71                     rightsub->balance = 0;
     72                     leftsub->balance = 0;
     73                     break;
     74                 case 1: // RLL型
     75                     r->balance = 0;
     76                     leftsub->balance = 0;
     77                     rightsub->balance = -1;
     78                     break;
     79                 case -1: // RLR型
     80                     rightsub->balance = 0;
     81                     leftsub->balance = 0;
     82                     r->balance= -1;
     83                     break;
     84             }
     85             RightLeft(r);  // RL折线型转换处理
     86             action = false;
     87             break;
     88     }
     89 }
     90 // 折线型LR处理
     91 template<class Type>
     92 void AVLtree<Type>::LeftRight(TNode<Type> *&r)
     93 {
     94     RightRight(r->leftChild); // 转换为LL型(一条直线)
     95     LeftLeft(r);  // LL型处理
     96 }
     97 // 折线型RL处理
     98 template<class Type>
     99 void AVLtree<Type>::RightLeft(TNode<Type> *&r)
    100 {
    101     LeftLeft(r->rightChild);  // 先转换为RR型(一条直线)
    102     RightRight(r);  // RR型处理
    103 }
    104 // 1. 把RL转换为RR  2. LL型处理
    105 template<class Type>
    106 void AVLtree<Type>::LeftLeft(TNode<Type> * &r) 
    107 {
    108     TNode<Type> *cur = r;          // cur暂存r
    109     r = r->leftChild;              // 改变r就是改变根
    110     cur->leftChild = r->rightChild;// 改变暂存cur  实现衔接
    111     r->rightChild = cur;           // 根的右子树置为cur
    112 }
    113 // 1. 把LR转换为LL  2. RR型处理
    114 template<class Type>
    115 void AVLtree<Type>::RightRight(TNode<Type> * &r)
    116 {
    117     TNode<Type> *cur = r;          // cur暂存r
    118     r = r->rightChild;             // 改变r就是改变根
    119     cur->rightChild = r->leftChild;// 改变暂存cur  实现衔接
    120     r->leftChild = cur;            // 根的左子树置为cur
    121 }
    122 // 左平衡处理过程
    123 template<class Type>
    124 void AVLtree<Type>::LeftBalance(TNode<Type> *&r, bool &action)
    125 {
    126     TNode<Type> *leftsub = r->leftChild;
    127     TNode<Type> *rightsub = leftsub->rightChild;
    128     switch (leftsub->balance)
    129     {
    130         case 1:// LL型
    131             leftsub->balance = 0;
    132             r->balance = 0;
    133             LeftLeft(r);
    134             action = false;
    135             break;
    136         case 0:
    137             action = false;
    138             break;
    139         case -1:// LR型
    140             switch (rightsub->balance)
    141             {
    142             case 0:// LR型
    143                 r->balance = 0;
    144                 rightsub->balance = 0;
    145                 leftsub->balance = 0;
    146                 break;
    147             case -1:// LRR型
    148                 r->balance = 0;
    149                 rightsub->balance = 0;
    150                 leftsub->balance = 1;
    151                 break;
    152             case 1:// LRL型
    153                 rightsub->balance = 0;
    154                 leftsub->balance = 0;
    155                 r->balance = -1;
    156                 break;
    157             }
    158             LeftRight(r);  // LR折线型转换处理
    159             action = false;
    160             break;
    161         }
    162 }
    163 // Insert主函数
    164 template<class Type>
    165 void AVLtree<Type>::Insert(TNode<Type> * & root, const Type &x, bool &action)
    166 {
    167     if (NULL == root)
    168     {
    169         root = new TNode<Type>(x);
    170         return;
    171     }
    172     else if (x > root->data)
    173     {
    174         Insert(root->rightChild, x, action);
    175         if (action) // 右子树插入成功
    176         {
    177             switch (root->balance)  // 需要重置根的平衡因子
    178             {
    179                 case 1: // 表示左子树已经存在,现再插入右子树成功
    180                     root->balance = 0;  //平衡因子置0
    181                     break;
    182                 case 0: // 表示之前平衡,现再插入右子树成功
    183                     root->balance = -1;  //平衡因子置1
    184                     break;
    185                 case -1: // 表示右子树已经存在,现再插入右子树成功
    186                     RightBalance(root, action);    //右平衡
    187                     break;
    188             }
    189         }
    190     }
    191     else if (x < root->data)
    192     {
    193         Insert(root->leftChild, x, action);
    194         if (action)  // 左子树插入成功
    195         {
    196             switch (root->balance)    // 需要重置根的平衡因子
    197             {
    198             case 1: // 平衡左子树
    199                 LeftBalance(root, action);
    200                 break;
    201             case 0:
    202                 root->balance = 1;
    203                 break;
    204             case -1:
    205                 root->balance = 0;
    206                 action = false;
    207                 break;
    208             }
    209         }
    210     }
    211     else
    212         cout << "数据" << x << "重复!" << endl;
    213 }
    214 // 查找当前节点的父节点
    215 template<class Type>
    216 TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *p, TNode<Type> *cur)
    217 {
    218     if (NULL == p || NULL == cur|| p == cur)
    219         return NULL;
    220     if (cur == p->leftChild || cur == p->rightChild)
    221         return p;
    222 
    223     if (p->data < cur->data)
    224         return Parent(p->rightChild, cur);
    225     else
    226         return Parent(p->leftChild, cur);
    227 }
    228 // 查找当前结点的后继 (先序遍历的后继)
    229 template<class Type>
    230 TNode<Type> *AVLtree<Type>::FindNodeNext(TNode<Type> *cur)
    231 {
    232     if (NULL == cur) 
    233         return NULL;
    234     TNode<Type> *p = cur->rightChild;
    235     while (p->leftChild != NULL)
    236     {
    237         p = p->leftChild;
    238     }
    239     return p;
    240 }
    241 //////////////////////////////////////////////////////////////////////
    242 /////////////////////////////////删除节点
    243 template<class Type>
    244 void AVLtree<Type>::DeleTNode(TNode<Type> *&cur, TNode<Type> *par)
    245 {
    246     if (NULL == cur)   
    247         return;
    248     //    情况一:删除的是根节点,那么它的父节点必定为NULL
    249     if (NULL == par)
    250     {    // cur可能是根结点,并且树仅仅只有一个根
    251         if (NULL == cur->rightChild && NULL == cur->leftChild)
    252         {
    253             delete cur;
    254             cur = NULL;
    255             return;
    256         }
    257         // 单分支的树
    258         if (NULL == cur->rightChild)
    259         {    // 右子树不存在
    260             TNode<Type> *p = cur;
    261             cur = cur->leftChild;
    262             delete p;
    263             p = NULL;
    264             return;
    265         }
    266         if (NULL == cur->leftChild)
    267         {    // 左子树不存在
    268             TNode<Type> *q = cur;
    269             cur = cur->rightChild;
    270             delete q;
    271             q = NULL;
    272             return;
    273         }
    274     }
    275     // 情况二:删除的属于双分支的节点
    276     if (cur->leftChild != NULL && cur->rightChild != NULL)
    277     {
    278         TNode<Type> *p = FindNodeNext(cur); // 锁定先序遍历的后继
    279         // 情况一:
    280         if (cur->rightChild == p)
    281         {    // 说明右子树仅仅只有一个节点
    282             cur->balance += 1;    // 删除之后平衡因子改变
    283             cur->data = p->data;  // 填充数据,意味着改变删除对象
    284             cur->rightChild = p->rightChild; // 衔接数据
    285             delete p;  //删除节点p
    286             p = NULL;
    287             return;
    288         }
    289         // 情况二:
    290         // 否则
    291         TNode<Type> *q = Parent(p); // 找到父节点
    292         if (q->balance != 0)  // 不等于0,说明删除后会影响根结点的平衡因子
    293           cur->balance += 1;    // 调整根节点的平衡因子
    294         // 否则
    295         q->balance -= 1;   // 删除的是左节点,所以加一
    296         cur->data = p->data; // 填充数据,意味着改变删除对象
    297         
    298         q->leftChild = p->rightChild; // 衔接数据
    299 
    300         // 最后才可以动手删除节点  删除节点  释放内存
    301         delete p;
    302         p = NULL;
    303         return;
    304     }
    305     // 情况三:单分支(其中包括了叶子节点的情况)
    306     if (NULL == cur->leftChild)
    307     {
    308         TNode<Type> *p = cur;
    309         if (cur == par->leftChild)
    310             par->leftChild = cur->rightChild;  // 衔接数据
    311         else 
    312             par->rightChild = cur->rightChild; // 衔接数据
    313 
    314         delete p;
    315         p = NULL;
    316         return;
    317     }
    318     if (NULL == cur->rightChild)
    319     {
    320         TNode<Type> *q = cur; 
    321         if (cur == par->leftChild)
    322             par->leftChild = cur->leftChild;
    323         else 
    324             par->rightChild = cur->leftChild;
    325 
    326         delete q;
    327         q = NULL;
    328         return;
    329     }
    330 }
    331 // 删除过程的主函数
    332 template<class Type>
    333 void AVLtree<Type>::Remove(TNode<Type> * &r, const Type &x, bool &action)
    334 {
    335     if (NULL == r)    
    336         return;
    337     if (x == r->data)
    338     {
    339         TNode<Type> *cur = r; // 确定数据的节点信息
    340         TNode<Type> *par = Parent(r);// 确定当前结点的父节点
    341         DeleTNode(r, par); // 删除当前指针
    342         return;
    343     }
    344     else if (x > r->data)
    345     {    // 右边查找
    346         Remove(r->rightChild, x, action);
    347         if (action)
    348         {
    349             switch (r->balance)
    350             {
    351             case -1: // 若原来为1,现在删除了右节点,应该为0
    352                 r->balance = 0;
    353                 break;
    354                 //若原来为-1,现在又再右枝上删除了节点,  
    355                 //树一定不平衡,需要左平衡调整
    356             case 1:   
    357                 LeftBalance(r, action);
    358                 action = false;
    359                 break;
    360             case 0: // 若原来为0,现在删除了右节点,应该为-1
    361                 r->balance = 1;
    362                 action = false;
    363                 break;
    364             }
    365         }
    366     }
    367     else if (x < r->data)
    368     {
    369         Remove(r->leftChild, x, action);
    370         if (action)
    371         {
    372             switch (r->balance)
    373             {
    374             case -1:// 若原来为1,现在又再左枝上删除了节点,
    375                     // 树一定不平衡,需要右平衡调整
    376                 RightBalance(r, action);
    377                 break;
    378             case 1:// 若原来为-1,现在删除了左节点,应该为0
    379                 r->balance = 0;
    380                 break;
    381             case 0:// 若原来为0,现在删除了左节点,应该为1
    382                 r->balance = -1;
    383                 action = false;
    384                 break;
    385             }
    386         }
    387     }
    388 }
    389 
    390 template<class Type>
    391 AVLtree<Type>::AVLtree(): root(NULL)
    392 {}
    393 template<class Type>
    394 void AVLtree<Type>::Insert(const Type &bt)
    395 {
    396     bool action = true;
    397     Insert(root, bt, action);
    398 }
    399 template<class Type>
    400 TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *cur)
    401 {
    402     return Parent(root, cur);
    403 }
    404 template<class Type>
    405 void AVLtree<Type>::Remove(const Type &x)
    406 {
    407     bool action = true;
    408     Remove(root, x, action);
    409 }
    410 template<class Type>
    411 void AVLtree<Type>::InOrder(TNode<Type> *p)
    412 {
    413     if (p != NULL)
    414     {
    415         InOrder(p->leftChild);
    416         cout << p->data << " ";
    417         InOrder(p->rightChild);
    418     }
    419 }
    420 template<class Type>
    421 void AVLtree<Type>::InOrder()
    422 {
    423     InOrder(root);
    424     cout << endl;
    425 }
    View Code

     

    Good  Good Study, Day  Day  Up.

    顺序  选择  循环  总结

  • 相关阅读:
    POJ 1082 博弈推规律
    博弈论总结
    POJ 2502 Subway 关键在建图
    【算法设计与数据结构】为何程序员喜欢将INF设置为0x3f3f3f3f?
    一位ACMer过来人的心得
    POJ1724 Dij队列优化邻接表
    Dijkstra队列优化矩阵版
    Uva247 Floyd传递闭包+map处理
    简爬新浪新闻网
    爬href链接
  • 原文地址:https://www.cnblogs.com/Braveliu/p/3467316.html
Copyright © 2020-2023  润新知