数据结构备忘录:保证AVL树删除操作正确性的原理的讨论

对AVL树首先要弄清它的定义:AVL树是一棵高度平衡的二叉搜索树,它要么是一棵空树,要么是一棵左右子树均为AVL树,且左右子树高度差的绝对值不大于一的二叉搜索树

数据结构教科书介绍的AVL树平衡化旋转共有四种方式:LR左单旋转,RR右单旋转,LRR先左后右双旋转,RLR先右后左双旋转,LR和RR,LRR和RLR互为镜像,若不熟悉请参看数据结构教科书,下面要对保证AVL树插入删除操作正确性的原理进行简单的讨论。

当在AVL树中删除一个节点时,按对二叉搜索树执行删除节点操作时采用的方式找到待删除节点,但由二叉搜索树删除算法(请参看数据结构教科书)可知,待删除节点不一定是实际删除节点,在某些情况下待删除节点没有被实际删除,而是将非待删除节点的实际删除节点的数据域替换带删除节点的数据域,此后删除的是实际被删除的节点而不是带删除节点,当然在另一些情况下,待删除节点就是实际删除节点。这样每当按对二叉搜索树执行删除操作的方式成功删除(注意待删除节点未必被实际删除)AVL树中的待删除节点后,通过指针定位到实际被删除节点的父节点及该父节点的被实际删除节点的子树的根节点,设指向该父节点的指针为parent,指向实际被删除节点的该父节点的子树的根节点的指针为q(可能为NULL),那么分别讨论可知,无论在AVL树中对待删除节点执行删除操作对应删除二叉搜索树中节点时可能出现的哪一种情形,以parent为根的子树总满足以下条件A:

1.以parent指向的节点为根节点的子树在执行删除操作前是AVL树(由AVL树定义)

2.以q指向的节点为根节点的子树在被删除一个节点后经过一系列或不经过平衡化旋转后,其高度相比删除前下降一,并且仍然为AVL树

以此为基础我们来寻找循环不变量

现假设存在一棵以parent指向的节点为根节点的二叉搜索树,在对它的子树执行删除操作前它是AVL树且该树是执行删除操作前原AVL树的一棵子树,

若在parent的左子树或右子树上按对二叉搜索树执行删除的方式删除一个节点后经过一系列或不经过平衡化旋转后,左子树的高度相比于删除前下降一并且仍然为AVL树(即parent树满足条件A),q为指向此时该子树根节点的指针,则对parent树而言有如下几种情形:

情形A

 

以parent指向的节点为根节点的AVL树A在执行删除前根节点平衡因子为0,在parent的左子树上删除一个节点并做或不做平衡化旋转调整后左子树高度下降一,此时parent平衡因子变为1,由于作删除操作的AVL树A满足条件A,以此为依据根据AVL树定义不难验证这时parent树仍然为AVL树,当然其高度相比于删除前没有任何变化,于是从树A根节点到原AVL树根节点的路径上各节点(除树A根节点)的平衡因子仍然和删除前相同,即这些节点仍然平衡,于是按AVL树的定义从A的根节点的父节点到原树根节点逐层向上递推,最后即得以A根节点到原树父节点的路径上的节点为根节点的子树均为AVL树,当然原树仍然为AVL树,于是可以结束平衡化过程

情形A*

 

和情形A对称,分析是类似的,此时对树A不做任何平衡化旋转,原树已平衡,结束平衡化过程

情形B

以parent指向的节点为根节点的AVL树A在执行删除前根节点平衡因子为-1,在parent的左子树上删除一个节点并做或不做平衡化旋转调整后左子树高度下降一,此时parent平衡因子变为0,由于作删除操作的AVL树A满足条件A,以此为依据根据AVL树定义不难验证这时parent树仍然为AVL树,且其高度相比于删除节点前下降一,此时不对A做任何平衡化旋转,这样就可以发现树A满足在树A上按对二叉搜索树执行删除的方式删除一个节点后经过一系列或不经过平衡化旋转后,树A的高度相比于删除前下降一并且仍然为AVL树,注意到树A高度降一影响到其根节点父节点平衡因子有可能使其失衡,所以令parent为树A根节点的父节点,q为树A根节点回溯至上一层再按各种情形进行相应的处理。这样做是合理的,因为此时以parent为根的子树(q为parent左子树或右子树根节点)刚好满足条件A,这样就能就各种情形以相同的方式进行同样的处理

情形C

以parent指向的节点为根节点的AVL树A右子树根节点平衡因子为0,在执行删除前根节点平衡因子为1,在parent的左子树上删除一个节点并做或不做平衡化旋转调整后左子树高度下降一,此时parent平衡因子变为2,树A失衡于是对树A做左单旋转,由于作删除操作的AVL树A满足条件A,以此为依据根据AVL树定义不难验证左单旋转后的树A仍然为AVL树,且其高度相比于删除前没有任何变化,于是从树A根节点到原AVL树根节点的路径上各节点(除树A根节点)的平衡因子仍然和删除前相同,即这些节点仍然平衡,于是按AVL树的定义从A的根节点的父节点到原树根节点逐层向上递推,最后即得以A根节点到原树父节点的路径上的节点为根节点的子树均为AVL树,当然原树仍然为AVL树,这样就可以结束平衡化过程

情形C*

和情形C对称,分析是类似的,此时对树A做右单旋转,然后原树已平衡,结束平衡化过程

 情形D

以parent指向的节点为根节点的AVL树A右子树根节点平衡因子为1,在执行删除前根节点平衡因子为1,在parent的左子树上删除一个节点并做或不做平衡化旋转调整后左子树高度下降一,此时parent平衡因子变为2,树A失衡于是对树A做左单旋转。由于作删除操作的AVL树A满足条件A,以此为依据根据AVL树定义不难验证左单旋转后的树A仍然为AVL树,且其高度相比于删除节点前下降一,这样就可以发现树A满足在树A上按对二叉搜索树执行删除的方式删除一个节点后经过一系列或不经过平衡化旋转后,树A的高度相比于删除前下降一并且仍然为AVL树,注意到树A高度降一影响到其根节点父节点平衡因子有可能使其失衡,所以令parent为树A根节点的父节点,q为树A根节点回溯至上一层再按各种情形进行相应的处理。这样做是合理的,因为此时以parent为根的子树(q为parent左子树或右子树根节点)刚好满足条件A,这样就能就各种情形以相同的方式进行同样的处理

情形D*

和情形D对称,分析是类似的,此时对树A做右单旋转,然后回溯至上一层继续平衡化

情形E

以parent指向的节点为根节点的AVL树A右子树根节点平衡因子为-1,在执行删除前根节点平衡因子为1,在parent的左子树上删除一个节点并做或不做平衡化旋转调整后左子树高度下降一,此时parent平衡因子变为2,树A失衡于是对树A做先右后左双旋转。由于作删除操作的AVL树A满足条件A,以此为依据根据AVL树定义不难验证先右后左双旋转后的树A仍然为AVL树,且其高度相比于删除节点前下降一,这样就可以发现树A满足在树A上按对二叉搜索树执行删除的方式删除一个节点后经过一系列或不经过平衡化旋转后,树A的高度相比于删除前下降一并且仍然为AVL树,注意到树A高度降一影响到其根节点父节点平衡因子有可能使其失衡,所以令parent为树A根节点的父节点,q为树A根节点回溯至上一层再按各种情形进行相应的处理。这样做是合理的,因为此时以parent为根的子树(q为parent左子树或右子树根节点)刚好满足条件A,这样就能就各种情形以相同的方式进行同样的处理

情形E*

和情形E对称,分析是类似的,此时对树A做先左后右双旋转,然后回溯至上一层继续平衡化

从以上讨论就可以看出循环不变量了,它就是parent子树满足的条件A,如果parent子树满足条件A且对应A,A* 两种情形,则不做平衡化旋转并结束平衡化,如果对应C,C*两种情形,则做单旋转并结束平衡化,如果对应B,B*两种情形则不做平衡化旋转并回溯至上一层平衡化(以parent父节点为根的子树满足条件A),若对应D,D*两种情形则做单旋转并回溯至上一层平衡化(以parent父节点为根的子树满足条件A),若对应E,E*两种情形,则做双旋转并回溯至上一层平衡化(以parent父节点为根的子树满足条件A).由此可以总结出删除AVL树某节点过程中经历的平衡化过程如下:

从本文开头提及的最初的parent子树开始,该parent子树满足条件A,q为parent子树被删除节点的子树的根节点指针(可能为NULL).

AVL树删除算法(调整平衡因子的细节没有给出,请参考下方代码):

(1)在AVL树上执行二叉搜索树删除算法,之后令parent为实际被删除节点的父节点,q为实际被删节点所在的该父节点的子树的根节点的指针

(2) if(parent子树对应于A,A* C,C*情形)

        A,A*情形,直接转3

        C情形 parent子树左单旋转, 然后转3

        C*情形 parent子树右单旋转, 然后转3

     else

        B,B*情形 如果 parent为根节点转3 否则 q=parent    parent=parent父节点转2

        D情形 parent子树左单旋转 随后如果 parent为根节点转3 否则q=parent    parent=parent父节点 转2

        D*情形 parent子树右单旋转 随后如果 parent为根节点转3 否则q=parent    parent=parent父节点 转2

        E情形 parent子树先右后左双旋转 随后如果 parent为根节点转3 否则q=parent    parent=parent父节点 转2

        E*情形 parent子树先左后右双旋转 随后如果 parent为根节点转3 否则q=parent    parent=parent父节点 转2

(3)结束

在这里发表一些个人看法,一些数据结构教科书上(如数据结构与算法分析:java语言描述)提到AVL树删除算法的正确编写有一定难度,实际上并非如此.从以上算法来看,编程实现时思路的推进完全是线性的,根本没有难度。非要说实现难度大,那也只能是琐碎的编码细节令人抓狂,事实上从

以上算法来看删除算法本质上非常简单,并不复杂,编写代码只需用心就能正确实现删除算法

下面讨论AVL树的插入

插入操作和删除相比更为简单,实现难度更低,分析插入操作还是要先寻找循环不变量

 首先插入新节点后只有新节点父节点至根节点的路径上的节点的平衡因子受影响,以路径上各节点为根的子树的高度要么加一要么不变,即平衡因子要么加减一要么不变。因此路径上各节点的平衡因子在插入新节点后的范围在-2至2之间

按最一般情形考虑,插入新节点(在非空树中插入)后,令parent为新插入节点父节点,q为新插入节点。若插入后parent平衡因子(不是为+-1就是为0)为0,则根据定义不难验证原树已平衡为AVL树,这样就可以结束平衡化过程,若平衡因子为+-1(插入前parent为叶节点),则令q=parent,parent为其父节点,这样parent子树满足条件B:

    q为AVL树    插入前q平衡因子为0,插入后绝对值为1,q高度相比于插入前加一,且此时没有对q或其子树做平衡化旋转

这样设有一棵原AVL树的子树,根节点为parent,parent的按二叉搜索树插入方式插入节点的子树根节点为q,parent满足条件B。根据节点插入parent右子树或左子树加减parent平衡因子,调整parent平衡因子为插入后平衡因子。然后,

如果parent平衡因子为+-1,则插入前为0,且parent高度相比于插入前加一,插入后parent仍然为AVL树,此时不对parent进行平衡化旋转,由于parent插入后高度加一parent父节点的平衡因子受到影响,因此令q=parent,parent=parent父节点,回溯到上一层按所列各情形进行平衡化操作。这样做是合理的,因为根据上述分析回溯到上一层后parent子树满足条件B,所以完全可以按照各情形以相同方式进行相同处理

如果parent平衡因子为0,则插入前parent平衡因子绝对值为1,即新节点在较矮的子树上插入,插入后parent左右子树等高,不难看出插入后parent子树仍为AVL树且高度相比于插入前不变,于是沿从parent父节点到原AVL树根节点的路径层层向上递推即可验证插入后原树仍为AVL树,故此时可结束平衡化过程

若parent平衡因子绝对值为2,则有以下几种情形:

情形一:

插入后parent平衡因子为-2,q平衡因子为-1,即在q的左子树上插入,左子树在插入后高度加一,q为parent左子树,此时直接对parent做右单旋转,根据做平衡化旋转前的parent树满足条件B和AVL树定义可验证旋转后parent仍然为AVL树,且高度相比于插入前不变,这样原树已平衡,直接结束平衡化过程

情形一*

 

和情形一对称,插入后parent平衡因子为2,q平衡因子为1,即在q的右子树上插入,右子树在插入后高度加一,q为parent右子树,此时对parent做左单旋转并结束平衡化过程

情形二:

插入后parent平衡因子为-2,q平衡因子为1,即在q的右子树上插入,q为parent左子树,q的右子树插入后高度增一,故必有q的右子女p(树C的根)。由于是在子树p上插入,所以p一定为从最初的parent子树的根节点至q的回溯路径上的一个节点,因此插入后p的平衡因子为+-1,插入前为0,因此一定为在p的两棵等高子树之一上插入,插入后子树p的高度状况如上图所示,此时直接对parent做先左后右双旋转,根据做平衡化旋转前的parent树满足条件B和AVL树定义可验证旋转后parent仍然为AVL树,且高度相比于插入前不变,这样原树已平衡,直接结束平衡化过程

情形二*

和情形二对称,分析是类似的,插入后parent平衡因子为2,q平衡因子为-1,即在q的左子树上插入,q为parent右子树,q的左子树插入后高度增一,故必有q的左子女p(树C的根)。由于是在子树p上插入,所以p一定为从最初的parent子树的根节点至q的回溯路径上的一个节点,因此插入后p的平衡因子为+-1,插入前为0,因此一定为在p的两棵等高子树之一上插入,插入后子树p的高度状况如上图所示,此时直接对parent做先右后左双旋转,根据做平衡化旋转前的parent树满足条件B和AVL树定义可验证旋转后parent仍然为AVL树,且高度相比于插入前不变,这样原树已平衡,直接结束平衡化过程

由以上讨论可以看出循环不变量就是parent子树满足的条件B,如果parent子树满足条件B,那么若parent在插入后的平衡因子绝对值为1,则令q=parent   parent=parent父节点  回溯到上一层继续按文中列出的情形进行平衡化,若parent在插入后的平衡因子为0,则直接结束平衡化过程,若parent在插入后的平衡因子绝对值为2,此时若parent子树对应情形一则对parent子树执行右单旋转并结束平衡化过程,对应情形一*则对parent子树执行左单旋转并结束平衡化过程,对应情形二则对parent子树执行先左后右双旋转并结束平衡化过程,对应情形二*则对parent子树执行先右后左双旋转并结束平衡化过程。

根据上述分析按和分析删除操作类似的方式就可以总结出AVL树的插入算法,可以自行分析,这里就不赘述了。

下面是删除与插入操作的具体代码实现,代码中加入判断是否为AVL树的代码(非递归)以检验删除操作的正确性,也就是每次删除插入成功后用判断函数检验删除插入后的二叉树是否为AVL树,从而检验插入删除算法的正确性

   1 #include "stdafx.h"
   2 #include <stack>
   3 #include <vector>
   4 #include <iostream>
   5 #include <string>
   6 #include <cmath>
   7 #include <algorithm>
   8 using namespace std;
   9 
  10 #define TYPE int
  11 template <typename T>
  12 struct AVLNode  //AVL树节点类
  13 {
  14     int bf;  //节点平衡因子
  15     T data;  //节点数据域
  16     AVLNode *left;
  17     AVLNode *right;
  18     AVLNode(int b, T d) :bf(b), data(d), left(nullptr), right(nullptr) {}
  19 };
  20 
  21 template <typename T>
  22 void RotateLR(AVLNode<T> *&ptr)  //对以ptr为根的子树执行先左后右双旋转,ptr成为旋转后新树根节点指针
  23 {
  24     AVLNode<T> *p = ptr->left;
  25     AVLNode<T> *q = p->right;
  26     p->right = q->left;
  27     q->left = p;
  28     ptr->left = q->right;
  29     q->right = ptr;
  30     if (q->bf == 0)
  31     {
  32         p->bf = ptr->bf = 0;
  33     }
  34     else
  35     {
  36         if (q->bf == -1)
  37         {
  38             p->bf = 0;
  39             ptr->bf = 1;
  40         }
  41         else
  42         {
  43             p->bf = -1;
  44             ptr->bf = 0;
  45         }
  46         q->bf = 0;
  47     }
  48     ptr = q;
  49 }
  50 
  51 template <typename T>
  52 void RotateRL(AVLNode<T> *&ptr)  //对以ptr为根的子树执行先右后左双旋转,ptr成为旋转后新树根节点指针
  53 {
  54     AVLNode<T> *p = ptr->right;
  55     AVLNode<T> *q = p->left;
  56     p->left = q->right;
  57     q->right = p;
  58     ptr->right = q->left;
  59     q->left = ptr;
  60     if (q->bf == 0)
  61     {
  62         p->bf = ptr->bf = 0;
  63     }
  64     else
  65     {
  66         if (q->bf == -1)
  67         {
  68             p->bf = 1;
  69             ptr->bf = 0;
  70         }
  71         else
  72         {
  73             p->bf = 0;
  74             ptr->bf = -1;
  75         }
  76         q->bf = 0;
  77     }
  78     ptr = q;
  79 }
  80 
  81 template <typename T>
  82 void RotateR(AVLNode<T> *&ptr)  //对以ptr为根的子树执行右单旋转,ptr成为旋转后新树根节点指针
  83 {
  84     AVLNode<T> *p = ptr->left;
  85     ptr->left = p->right;
  86     p->right = ptr;
  87     if (p->bf == -1)
  88     {
  89         p->bf = ptr->bf = 0;
  90     }
  91     else
  92     {
  93         p->bf = 1;
  94     }
  95     ptr = p;
  96 }
  97 
  98 template <typename T>
  99 void RotateL(AVLNode<T> *&ptr)  ////对以ptr为根的子树执行左单旋转,ptr成为旋转后新树根节点指针
 100 {
 101     AVLNode<T> *p = ptr->right;
 102     ptr->right = p->left;
 103     p->left = ptr;
 104     if (p->bf == 0)
 105     {
 106         p->bf = -1;
 107         ptr->bf = 1;
 108     }
 109     else
 110     {
 111         ptr->bf = p->bf = 0;
 112     }
 113     ptr = p;
 114 }
 115 
 116 template <typename T>
 117 bool isAVL(AVLNode<T> *root)  //判断以root为根节点的二叉树是否为AVL树
 118 {
 119     struct temp  
 120     {
 121         T lmin;  //节点左子树中最小节点值
 122         T lmax;  //节点左子树中最大节点值
 123         T rmin;  //节点右子树中最小节点值
 124         T rmax;  //节点右子树中最大节点值
 125     };
 126     struct memory
 127     {
 128         AVLNode<T> *p;
 129         int direction;
 130         temp minmax;  
 131         int lh= 0;   //节点左子树高度
 132         int rh= 0;   //节点右子树高度
 133         memory(AVLNode<T> *p, int d) :p(p), direction(d) {}
 134     };
 135     int d = 0;
 136     AVLNode<T> *ptr = root;
 137     AVLNode<T> *const dest = ptr;
 138     stack<memory> arrange;
 139     bool TF = false;
 140     while (true)
 141     {
 142         if (Searchd(ptr, d) == 0)
 143         {
 144             if (ptr == dest)
 145             {
 146                 if (d == 0)
 147                     return true;
 148                 else
 149                 {
 150                     if (ptr->left == nullptr || ptr->right != nullptr)
 151                     {
 152                         if (ptr->data < arrange.top().minmax.rmin)
 153                         {
 154                             if (abs(arrange.top().rh - arrange.top().lh) > 1)
 155                             {
 156                                 cout << "存在左右子树高度差绝对值大于一的子树,原树非AVL树" << endl;
 157                                 return false;
 158                             }
 159                             arrange.pop();
 160                         }
 161                         else
 162                         {
 163                             cout << "当前树非二叉搜索树,也非AVL树" << endl;
 164                             return false;
 165                         }
 166                     }
 167                     else
 168                     {
 169                         if (ptr->data > arrange.top().minmax.lmax)
 170                         {
 171                             if (abs(arrange.top().rh - arrange.top().lh) > 1)
 172                             {
 173                                 cout << "存在左右子树高度差绝对值大于一的子树,原树非AVL树" << endl;
 174                                 return false;
 175                             }
 176                             arrange.pop();
 177                         }
 178                         else
 179                         {
 180                             cout << "当前树非二叉搜索树,也非AVL树" << endl;
 181                             return false;
 182                         }
 183                     }
 184                     return true;
 185                 }
 186             }
 187             else
 188             {
 189                 if (d == 0)
 190                 {
 191                     if (arrange.top().direction == 1)
 192                     {
 193                         arrange.top().lh = 1;
 194                         arrange.top().minmax.lmin = ptr->data;
 195                         arrange.top().minmax.lmax = ptr->data;
 196                     }
 197                     else
 198                     {
 199                         arrange.top().rh = 1;
 200                         arrange.top().minmax.rmin = ptr->data;
 201                         arrange.top().minmax.rmax = ptr->data;
 202                     }
 203                 }
 204                 else
 205                 {
 206                     if (ptr->left == nullptr || ptr->right != nullptr)
 207                     {
 208                         if (ptr->data < arrange.top().minmax.rmin)
 209                         {
 210                             temp temp1 = arrange.top().minmax;
 211                             int leftheight = arrange.top().lh;
 212                             int rightheight = arrange.top().rh;
 213                             arrange.pop();
 214 
 215                             if (arrange.top().direction == 1)
 216                             {
 217                                 if (ptr->left == nullptr)
 218                                 {
 219                                     arrange.top().minmax.lmin = ptr->data;
 220                                 }
 221                                 else
 222                                 {
 223                                     arrange.top().minmax.lmin = temp1.lmin;
 224                                 }
 225                                 arrange.top().minmax.lmax = temp1.rmax;
 226 
 227                                 if (abs(rightheight - leftheight) > 1)
 228                                 {
 229                                     cout << "存在左右子树高度差绝对值大于一的子树,原树非AVL树" << endl;
 230                                     return false;
 231                                 }
 232                                 else
 233                                 {
 234                                     arrange.top().lh = max(leftheight, rightheight) + 1;
 235                                 }
 236                             }
 237                             else
 238                             {
 239                                 if (ptr->left == nullptr)
 240                                 {
 241                                     arrange.top().minmax.rmin = ptr->data;
 242                                 }
 243                                 else
 244                                 {
 245                                     arrange.top().minmax.rmin = temp1.lmin;
 246                                 }
 247                                 arrange.top().minmax.rmax = temp1.rmax;
 248 
 249                                 if (abs(rightheight - leftheight) > 1)
 250                                 {
 251                                     cout << "存在左右子树高度差绝对值大于一的子树,原树非AVL树" << endl;
 252                                     return false;
 253                                 }
 254                                 else
 255                                 {
 256                                     arrange.top().rh = max(leftheight, rightheight) + 1;
 257                                 }
 258                             }
 259                         }
 260                         else
 261                         {
 262                             cout << "当前树非二叉搜索树,也非AVL树" << endl;
 263                             return false;
 264                         }
 265                     }
 266                     else
 267                     {
 268                         if (ptr->data > arrange.top().minmax.lmax)
 269                         {
 270                             temp temp1 = arrange.top().minmax;
 271                             int leftheight = arrange.top().lh;
 272                             int rightheight = arrange.top().rh;
 273                             arrange.pop();
 274                             if (arrange.top().direction == 1)
 275                             {
 276                                 arrange.top().minmax.lmin = temp1.lmin;
 277                                 arrange.top().minmax.lmax = ptr->data;
 278 
 279                                 if (abs(rightheight - leftheight) > 1)
 280                                 {
 281                                     cout << "存在左右子树高度差绝对值大于一的子树,原树非AVL树" << endl;
 282                                     return false;
 283                                 }
 284                                 else
 285                                 {
 286                                     arrange.top().lh = max(leftheight, rightheight) + 1;
 287                                 }
 288                             }
 289                             else
 290                             {
 291                                 arrange.top().minmax.rmin = temp1.lmin;
 292                                 arrange.top().minmax.rmax = ptr->data;
 293 
 294                                 if (abs(rightheight - leftheight) > 1)
 295                                 {
 296                                     cout << "存在左右子树高度差绝对值大于一的子树,原树非AVL树" << endl;
 297                                     return false;
 298                                 }
 299                                 else
 300                                 {
 301                                     arrange.top().rh = max(leftheight, rightheight) + 1;
 302                                 }
 303                             }
 304                         }
 305                         else
 306                         {
 307                             cout << "当前树非二叉搜索树,也非AVL树" << endl;
 308                             return false;
 309                         }
 310                     }
 311                 }
 312                 ptr = arrange.top().p;
 313                 d = arrange.top().direction;
 314             }
 315         }
 316         else
 317         {
 318             AVLNode<T> *interval = nullptr;
 319             if (d == 0)
 320             {
 321                 arrange.push(memory(ptr, Searchd(ptr, d)));
 322                 if (arrange.top().direction == 1)
 323                     interval = ptr->left;
 324                 else
 325                     interval = ptr->right;
 326             }
 327             else
 328             {
 329                 if (!(ptr->data > arrange.top().minmax.lmax))
 330                 {
 331                     cout << "当前树非二叉搜索树,也非AVL树" << endl;
 332                     return false;
 333                 }
 334                 arrange.top().direction = 2;
 335                 interval = ptr->right;
 336             }
 337             d = 0;
 338             ptr = interval;
 339         }
 340     }
 341 }
 342 
 343 template <typename T>
 344 AVLNode<T> *DelAVL(AVLNode<T> *root, T key)  //在以root为根节点的AVL树中删除关键码key
 345 {
 346     //AVL树的删除
 347     AVLNode<T> *p = root;
 348     stack<AVLNode<T> *> stackforflashback;
 349     while (p != nullptr)         //搜索被删除节点,同时将回溯路径记录在栈中
 350     {
 351         if (p->data == key)
 352             break;
 353         else
 354         {
 355             stackforflashback.push(p);
 356             if (key < p->data)
 357             {
 358                 p = p->left;
 359             }
 360             else
 361             {
 362                 p = p->right;
 363             }
 364         }
 365     }
 366 
 367     if (p != nullptr)  //被删除节点存在,被p指向
 368     {
 369         AVLNode<T> *parent = nullptr;
 370         AVLNode<T> *q = nullptr;
 371         if (p->left != nullptr && p->right != nullptr)   //被删节点左右子树均存在
 372         {
 373             q = p->right;
 374             if (q->left != nullptr)   //被删节点右子树根节点有左子树
 375             {
 376                 parent = p;
 377                 stackforflashback.push(parent);
 378                 while (q->left != nullptr)  //在被删节点右子树根节点左子树中搜索中序遍历的第一个节点,同时用栈记录回溯路径
 379                 {
 380                     parent = q;
 381                     q = q->left;
 382                     if (q->left != nullptr)
 383                         stackforflashback.push(parent);
 384                 }
 385                 parent->left = q->right;  //用该节点数据域替换被删节点数据域,将其右子树链接至其父节点左链指针,随后删除该节点
 386                 p->data = q->data;
 387                 delete q;
 388                 q = parent->left; //parent为需要做或不做平衡化旋转的第一棵子树根节点指针,q为该子树左子树根节点指针
 389 
 390             }
 391             else
 392             {
 393                 p->right = q->right;   //用被删节点右子女数据域替换被删节点指针域,将右子女右子树链接至被删节点右链指针,并删除右子女
 394                 p->data = q->data;
 395                 delete q;
 396                 parent = p;
 397                 q = p->right;  //parent为需要做或不做平衡化旋转的第一棵子树根节点指针,q为该子树左子树根节点指针
 398             }
 399         }
 400         else
 401         {
 402             if (p->left != nullptr)  //被删节点左子树不空,右子树空
 403             {
 404                 if (stackforflashback.empty() == false)  //被删节点有父节点
 405                 {
 406                     parent = stackforflashback.top();
 407                     stackforflashback.pop();
 408                     if (parent->left == p)
 409                     {
 410                         parent->left = p->left;
 411                         delete p;
 412                         q = parent->left;
 413                     }                     //将被删节点左子树链接至被删节点父节点相应链指针,并删除被删节点
 414                     else
 415                     {
 416                         parent->right = p->left;
 417                         delete p;
 418                         q = parent->right;
 419                     }                          //parent为需要做或不做平衡化旋转的第一棵子树根节点指针,q为该子树左子树根节点指针
 420                 }
 421                 else
 422                 {
 423                     parent = p->left;
 424                     delete p;         //删除被删节点后原AVL树恢复平衡,parent为根节点结束
 425                     return parent;
 426                 }
 427             }
 428             else if (p->right != nullptr)  //处理过程和以上情形完全对称
 429             {
 430                 if (stackforflashback.empty() == false)
 431                 {
 432                     parent = stackforflashback.top();
 433                     stackforflashback.pop();
 434                     if (parent->left == p)
 435                     {
 436                         parent->left = p->right;
 437                         delete p;
 438                         q = parent->left;
 439                     }
 440                     else
 441                     {
 442                         parent->right = p->right;
 443                         delete p;
 444                         q = parent->right;
 445                     }               //parent为需要做或不做平衡化旋转的第一棵子树根节点指针,q为该子树左子树根节点指针
 446                 }
 447                 else
 448                 {
 449                     parent = p->right;
 450                     delete p;   //删除被删节点后原AVL树恢复平衡,parent为根节点结束
 451                     return parent;
 452                 }
 453             }
 454             else        //被删节点为叶节点
 455             {
 456                 if (stackforflashback.empty() == false)   //被删叶节点有父节点
 457                 {
 458                     parent = stackforflashback.top();
 459                     stackforflashback.pop();
 460                     if (parent->left == p)
 461                     {
 462                         parent->left = nullptr;
 463                         delete p;
 464                         q = parent->left;
 465                     }
 466                     else                          //删除叶节点并将其父节点对应指针域置空
 467                     {
 468                         parent->right = nullptr;
 469                         delete p;
 470                         q = parent->right;
 471                     }                        //parent为需要做或不做平衡化旋转的第一棵子树根节点指针,q为该子树左子树根节点指针
 472                 }
 473                 else
 474                 {
 475                     parent = nullptr;
 476                     delete p;       //删除被删节点后原AVL树恢复平衡,parent为根节点结束
 477                     return parent;
 478                 }
 479             }
 480         }
 481         bool TF = false;
 482         do
 483         {
 484             if (TF == true)
 485                 stackforflashback.pop();
 486             else
 487                 TF = true;
 488 
 489             if ((parent->bf == 1 || parent->bf == -1) && q == nullptr && parent->right == nullptr && parent->left == nullptr)
 490             {
 491                 parent->bf = 0;
 492                 if (stackforflashback.empty() == false)
 493                 {
 494                     q = parent;
 495                     parent = stackforflashback.top();
 496                     continue;
 497                 }
 498                 else
 499                 {
 500                     return root;
 501                 }
 502 
 503             }
 504 
 505             if (parent->left == q)
 506             {
 507                 if (parent->bf == 0)
 508                 {
 509                     parent->bf = 1;   //情形a
 510                     return root;
 511                 }
 512                 else if (parent->bf == -1)
 513                 {
 514                     parent->bf = 0;
 515                     if (stackforflashback.empty() == false)
 516                     {
 517                         q = parent;
 518                         parent = stackforflashback.top();
 519                         continue;                            //情形b
 520                     }
 521                     else
 522                     {
 523                         return root;
 524                     }
 525                 }
 526                 else
 527                 {
 528                     p = parent->right;
 529                     q = parent;
 530                     if (p->bf == 0) 
 531                     {                            //情形c
 532                         if (stackforflashback.empty() == false)
 533                         {
 534                             RotateL(parent);//对以parent为根的子树执行左单旋转
 535                             if (q == stackforflashback.top()->left)
 536                             {
 537                                 stackforflashback.top()->left = parent;
 538                             }
 539                             else
 540                             {
 541                                 stackforflashback.top()->right = parent;
 542                             }
 543                         }
 544                         else
 545                         {
 546                             RotateL(parent);//对以parent为根的子树执行左单旋转
 547                         }
 548                         if (q == root)
 549                         {
 550                             return parent;
 551                         }
 552                         else
 553                         {
 554                             return root;
 555                         }
 556                     }
 557                     else if (p->bf == 1)   //情形d
 558                     {
 559                         RotateL(parent);//对以parent为根的子树执行左单旋转
 560                     }
 561                     else            //情形e
 562                     {
 563                         RotateRL(parent);//对以parent为根的子树执行先右后左双旋转
 564                     }
 565 
 566                     if (stackforflashback.empty() == false)
 567                     {
 568                         if (q == stackforflashback.top()->left)
 569                         {
 570                             stackforflashback.top()->left = parent;
 571                         }
 572                         else
 573                         {
 574                             stackforflashback.top()->right = parent;
 575                         }
 576                         q = parent;
 577                         parent = stackforflashback.top();
 578                     }
 579                     else
 580                     {
 581                         q = parent;
 582                     }
 583                 }
 584             }
 585             else
 586             {
 587                 if (parent->bf == 0)  //情形a*
 588                 {
 589                     parent->bf = -1;
 590                     return root;
 591                 }
 592                 else if (parent->bf == 1)   //情形b*
 593                 {
 594                     parent->bf = 0;
 595                     if (stackforflashback.empty() == false)
 596                     {
 597                         q = parent;
 598                         parent = stackforflashback.top();
 599                         continue;                            //情形b
 600                     }
 601                     else
 602                     {
 603                         return root;
 604                     }
 605                 }
 606                 else
 607                 {
 608                     p = parent->left;
 609                     q = parent;
 610                     if (p->bf == 0)          //情形c*
 611                     {
 612                         if (stackforflashback.empty() == false)
 613                         {
 614                             RotateR(parent);//对以parent为根的子树执行右单旋转
 615                             if (q == stackforflashback.top()->left)
 616                             {
 617                                 stackforflashback.top()->left = parent;
 618                             }
 619                             else
 620                             {
 621                                 stackforflashback.top()->right = parent;
 622                             }
 623                         }
 624                         else
 625                         {
 626                             RotateR(parent);//对以parent为根的子树执行右单旋转
 627                         }
 628                         if (q == root)
 629                         {
 630                              return parent;
 631                         }
 632                         else
 633                         {
 634                              return root;
 635                         }
 636                     }
 637                     else if (p->bf == -1)    //情形d*
 638                     {
 639                         RotateR(parent);//对以parent为根的子树执行右单旋转
 640                     }
 641                     else    //情形e*
 642                     {
 643                         RotateLR(parent);//对以parent为根的子树执行先左后右双旋转
 644                     }
 645 
 646                     if (stackforflashback.empty() == false)
 647                     {
 648                         if (q == stackforflashback.top()->left)
 649                         {
 650                             stackforflashback.top()->left = parent;
 651                         }
 652                         else
 653                         {
 654                             stackforflashback.top()->right = parent;
 655                         }
 656                         q = parent;
 657                         parent = stackforflashback.top();
 658                     }
 659                     else
 660                     {
 661                         q = parent;
 662                     }
 663                 }
 664             }
 665         } while (stackforflashback.empty() == false);
 666         return q;   //原AVL树已恢复平衡,返回根节点
 667     }
 668     else
 669     {
 670         cout << "AVL树中不存在要删除的数据元素,删除失败" << endl;
 671         return nullptr;
 672     }
 673 }
 674 
 675 template <typename T>
 676 AVLNode<T> *InsertAVL(AVLNode<T> *root, T key)
 677 {
 678     //AVL树的插入
 679     if (root == nullptr)
 680         return new AVLNode<T>(0, key);
 681     else
 682     {
 683         stack<AVLNode<T> *> stackforflashback;
 684         AVLNode<T> *p = root;
 685         while (p != nullptr)   //搜索插入位置
 686         {
 687             stackforflashback.push(p);
 688             if (key < p->data)
 689                 p = p->left;
 690             else if (key > p->data)
 691                 p = p->right;
 692             else
 693             {
 694                 cout << "要插入的关键字在AVL树中已存在,插入失败" << endl;
 695                 return nullptr;
 696             }
 697         }
 698 
 699         if (key < stackforflashback.top()->data)
 700         {
 701             stackforflashback.top()->left = new AVLNode<T>(0, key);   //新节点插入并调整父节点平衡因子
 702             --stackforflashback.top()->bf;
 703         }
 704         else
 705         {
 706             stackforflashback.top()->right = new AVLNode<T>(0, key);
 707             ++stackforflashback.top()->bf;
 708         }
 709 
 710         if (stackforflashback.top()->bf == 0)
 711         {
 712             return root;  //已平衡结束,返回根节点
 713         }
 714         else
 715         {
 716             p = stackforflashback.top();
 717             stackforflashback.pop();
 718             if (stackforflashback.empty() == false)
 719             {
 720                 AVLNode<T> *parent = nullptr;
 721                 while (stackforflashback.empty() == false)
 722                 {
 723                     parent = stackforflashback.top();
 724                     stackforflashback.pop();
 725                     if (parent->left == p)
 726                     {
 727                         --parent->bf;
 728                         if (parent->bf == 0)
 729                         {
 730                             return root;//已平衡,返回根节点
 731                         }
 732                         else if(parent->bf == -2)
 733                         {
 734                             AVLNode<T> *q = parent;
 735                             if (p->bf == 1)
 736                             {
 737                                RotateLR(parent);//对parent为根的子树执行先左后右双旋转
 738                                              //已平衡
 739                             }
 740                             else
 741                             {
 742                                RotateR(parent);//对以parent为根子树执行右单旋转
 743                                             //已平衡
 744                             }
 745 
 746                             if (stackforflashback.empty() == false)
 747                             {
 748                                 if (stackforflashback.top()->left == q)
 749                                     stackforflashback.top()->left = parent;
 750                                 else
 751                                     stackforflashback.top()->right = parent;
 752                             }
 753 
 754                             if (q == root)   //返回恢复平衡的AVL树根节点
 755                                return parent;
 756                             else
 757                                return root;
 758                         }
 759                         else
 760                         {
 761                             p = parent;  //以parent为根的子树已平衡其高度加一回溯至父节点
 762                         }
 763                     }
 764                     else
 765                     {
 766                         ++parent->bf;
 767                         if (parent->bf == 0)
 768                         {
 769                             //已平衡,返回根节点
 770                             return root;
 771                         }
 772                         else if (parent->bf == 2)
 773                         {
 774                             AVLNode<T> *q = parent;
 775                             if (p->bf == -1)
 776                             {
 777                                 RotateRL(parent);//对parent为根的子树执行先右后左双旋转
 778                                                  //已平衡
 779                             }
 780                             else
 781                             {
 782                                 RotateL(parent);//对以parent为根的子树执行左单旋转
 783                                                 //已平衡
 784                             }
 785 
 786                             if (stackforflashback.empty() == false)
 787                             {
 788                                 if (stackforflashback.top()->left == q)
 789                                     stackforflashback.top()->left = parent;
 790                                 else
 791                                     stackforflashback.top()->right = parent;
 792                             }
 793                             if (q == root)     //返回恢复平衡的AVL树根节点
 794                                 return parent;
 795                             else
 796                                 return root;
 797                         }
 798                         else
 799                         {
 800                             p = parent;  //以parent为根的子树已平衡其高度加一回溯至父节点
 801                         }
 802                     }
 803                 }
 804                 return p;   //原AVL树已平衡,返回根节点
 805             }
 806             else
 807             {
 808                 return p;
 809                 //原AVL树已平衡,返回根节点,结束
 810             }
 811         }
 812     }
 813 }
 814 
 815 template <typename T>
 816 int Searchd(AVLNode<T> *ptr, int d)
 817 {
 818     if (d == 2)
 819         return 0;
 820     else
 821     {
 822         if (d == 1)
 823         {
 824             if (ptr->right == nullptr)
 825                 return 0;
 826             else
 827                 return 2;
 828         }
 829         else
 830         {
 831             if (ptr->left != nullptr)
 832                 return 1;
 833             else
 834             {
 835                 if (ptr->right != nullptr)
 836                     return 2;
 837                 else
 838                     return 0;
 839             }
 840         }
 841     }
 842 }
 843 
 844 template <typename T>
 845 void output(AVLNode<T> *ptr)  //输出以ptr为根的AVL树对应的广义表形式
 846 {
 847     struct memory
 848     {
 849         AVLNode<T> *p;
 850         int direction;
 851         int last;
 852         memory(AVLNode<T> *p, int d, int l) :p(p), direction(d), last(l) {}
 853     };
 854     int d = 0;
 855     AVLNode<T> *const dest = ptr;
 856     stack<memory> arrange;
 857     while (true)
 858     {
 859         if (Searchd(ptr, d) == 0)
 860         {
 861             if (ptr == dest)
 862             {
 863                 if (d == 0)
 864                     cout <<ptr->data<< "(";
 865                 else
 866                 {
 867                     if (arrange.top().last == 1)
 868                         cout << ", ";
 869                 }
 870                 cout << ")";
 871                 break;
 872             }
 873             else
 874             {
 875                 if (d == 0)
 876                 {
 877                     if (arrange.top().last == 0)
 878                     {
 879                         if (arrange.top().direction == 1)
 880                         {
 881                             cout << ptr->data;
 882                             arrange.top().last = 1;
 883                         }
 884                         else
 885                         {
 886                             cout << " ," << ptr->data;
 887                             arrange.top().last = 2;
 888                         }
 889                     }
 890                     else 
 891                     {
 892                         cout << ",";
 893                         cout << ptr->data;
 894                         arrange.top().last = 2;
 895                     }
 896                 }
 897                 else
 898                 {
 899                     if (arrange.top().last ==2)
 900                       cout << ")";
 901                     else
 902                     {
 903                         cout << ", )";
 904                     }
 905                     arrange.pop();
 906                 }
 907                 ptr = arrange.top().p;
 908                 d = arrange.top().direction;
 909             }
 910         }
 911         else
 912         {
 913             AVLNode<T> *interval = nullptr;
 914             if (d == 0)
 915             {
 916                 if (arrange.empty() == false)
 917                 {
 918                     if (arrange.top().last == 0)
 919                     {
 920                         if (arrange.top().direction == 1)
 921                         {
 922                             cout << ptr->data <<"(";
 923                             arrange.top().last = 1;
 924                         }
 925                         else
 926                         {
 927                             cout << " ," << ptr->data << "(";
 928                             arrange.top().last = 2;
 929                         }
 930                     }
 931                     else
 932                     {
 933                         cout << ",";
 934                         cout << ptr->data<<"(";
 935                         arrange.top().last = 2;
 936                     }
 937                 }
 938                 else
 939                 {
 940                     cout << ptr->data << "(";
 941                 }
 942                 arrange.push(memory(ptr, Searchd(ptr, d), 0));
 943                 if (arrange.top().direction == 1)
 944                     interval = ptr->left;
 945                 else
 946                     interval = ptr->right;
 947             }
 948             else
 949             {
 950                 arrange.top().direction = 2;
 951                 interval = ptr->right;
 952             }
 953             d = 0;
 954             ptr = interval;
 955         }
 956     }
 957 }
 958 int main()
 959 {
 960     vector<TYPE> insertvalue{ 13, 5, 3, 2, 1, 4, 10, 8, 7, 6, 9, 11, 12, 16, 14, 15, 18, 17, 20, 19 };
 961     AVLNode<TYPE> *root = nullptr;
 962     for (vector<TYPE>::const_iterator p = insertvalue.cbegin(); p != insertvalue.cend(); ++p)
 963     {
 964         cout << "插入节点" << *p << endl;
 965         root = InsertAVL(root, *p);
 966         output(root);
 967         cout << endl;
 968         if (isAVL(root) == true)
 969         {
 970             cout << "当前树是AVL树";
 971             cout << endl;
 972         }
 973         else
 974         {
 975             cerr << "错误当前树不是AVL树!" << endl;
 976             exit(0);
 977         }
 978     }
 979     cout << endl;
 980     cout << "插入完成后删除前AVL树对应的广义表形式为:" << endl;
 981     output(root);
 982     cout << endl;
 983     cout << endl;
 984     for (vector<TYPE>::const_iterator p = insertvalue.cbegin(); p != insertvalue.cend(); ++p)
 985     {
 986         cout << "删除节点" << *p << endl;
 987         root = DelAVL(root, *p);
 988         if (root != nullptr)
 989         {
 990             output(root);
 991             cout << endl;
 992             if (isAVL(root) == true)
 993             {
 994                 cout << "当前树是AVL树";
 995                 cout << endl;
 996             }
 997             else
 998             {
 999                 cerr << "错误当前树不是AVL树!" << endl;
1000                 exit(0);
1001             }
1002         }
1003         else
1004             cout << "NULL";
1005         cout << endl;
1006     }
1007     return 0;
1008 }

 运行结果:

猜你喜欢

转载自www.cnblogs.com/WSKIT/p/8934474.html