查找(AVL平衡二叉树)

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

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

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

《查找(AVL平衡二叉树)》

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

平衡二叉树的基本认识:

《查找(AVL平衡二叉树)》

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

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

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

《查找(AVL平衡二叉树)》

《查找(AVL平衡二叉树)》

《查找(AVL平衡二叉树)》

《查找(AVL平衡二叉树)》

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

《查找(AVL平衡二叉树)》

【4】平衡二叉树的实现

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

《查找(AVL平衡二叉树)》《查找(AVL平衡二叉树)》

 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.

顺序  选择  循环  总结

    原文作者:kaizen
    原文地址: https://www.cnblogs.com/Braveliu/p/3467316.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞