AVL树实现(插入删除)

在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 “An algorithm for the organization of information” 中发表了它
好的,废话不多说了,有关AVL树的插入和删除详细介绍点击这里,直接上代码吧。

github地址:点击这里

 1 #ifndef _AVLTREE_H
  2 #define _AVLTREE_H
  3
  4 #include<iostream>
  5 #include<stack>
  6 using namespace std;
  7
  8 template<class E,class K>
  9 class AVLTree;
 10
 11 template<class E,class K>
 12 class AVLNode           //AVLNode结点的类定义
 13 {
 14 friend AVLTree<E,K>;
 15 private:
 16     E data;             //平衡因子
 17     AVLNode<E,K> *left,*right;
 18     int bf;
 19 public:
 20     AVLNode():left(NULL),right(NULL),bf(0)
 21     {}
 22     AVLNode(E d,AVLNode<E,K> *l = NULL,AVLNode<E,K> *r = NULL):data(d),left(l),right(r),bf(0)
 23     {}
 24 };
 25
 26 template<class E,class K>       //平衡二叉搜索树的类定义
 27 class AVLTree
 28 {
 29 private:
 30     AVLNode<E,K> *root; //根结点
 31     K RefValue;             //结束标志
 32 protected:
 33     AVLNode<E,K>* Search(K x,AVLNode<E,K> *& ptr)const;
 34     bool Insert(AVLNode<E,K> *& ptr,E& el);
 35     bool Remove(AVLNode<E,K> *& ptr,E k);
 36     void RotateL(AVLNode<E,K> *& ptr);      //左单旋
  37     void RotateR(AVLNode<E,K> *& ptr);      //右单旋
 38     void RotateLR(AVLNode<E,K> *& ptr);     //先左后右单旋
 39     void RotateRL(AVLNode<E,K> *& ptr);     //先右后左单旋
 40     int Height(AVLNode<E,K> *ptr)const;     //求高度
 41 public:
 42     AVLTree():root(NULL)        //构造空二叉树
 43     {}
 44     AVLTree(K Ref):RefValue(Ref),root(NULL)     //构造函数 构造非空二叉树
 45     {}
 46     bool Insert(E& el)
 47     {
 48         return Insert(root,el);
 49     }
 50     bool Remove(E el)
 51     {
 52         return Remove(root,el);
 53     }
 54     friend istream& operator >> (istream& in,AVLTree<E,K>& Tree);
 55     friend ostream& operator >> (ostream* out,AVLTree<E,K>& Tree);
 56     int Height()const;
 57 };
 58
 59 template<class E,class K>
 60 void AVLTree<E,K>::RotateL(AVLNode<E,K> *& ptr)     //左单旋转算法
 61 {
 62     AVLNode<E,K> *subL = ptr;           //要左旋的结点
 63     ptr = subL->right;                  //原根的右子女
 64     subL->right = ptr->left;            //ptr成为新根前卸掉其左边负载
 65     ptr->left = subL;                   //左单旋转,ptr为新根
 66     ptr->bf = subL->bf = 0;             //新的平衡因子
 67 }
 68
 69 template<class E,class K>
 70 void AVLTree<E,K>::RotateR(AVLNode<E,K> *& ptr)     //右单旋转算法
 71 {
 72     AVLNode<E,K> *subR = ptr;           //要右旋转的结点
  73     ptr = subR->left;                   //原根的左子女
 74     subR->left = ptr->right;            //ptr成为新根前卸掉其右边负载
 75     ptr->right = subR;                  //右单旋转,ptr为新根
 76     ptr->bf = subR->bf = 0;             //改变平衡因子
 77 }
 78
 79 template<class E,class K>
 80 void AVLTree<E,K>::RotateLR(AVLNode<E,K> *& ptr)    //先左后右双旋转
 81 {
 82     AVLNode<E,K> *subL,*subR;       //
 83     subL = ptr->left;
 84     subR = ptr;
 85     ptr = subL->right;
 86     subL->right = ptr->left;        //ptr成为新根前甩掉它左边的负载
 87     ptr->left = subL;               //左单旋转,ptr成为新根
 88     if(ptr->bf <= 0)        //说明新增结点在左边给了subL
 89         subL->bf = 0;
 90     else                    //说明新增结点在右边给了subR
 91         subL->bf = -1;
 92     subR->left = ptr->right;        //ptr成为新根前甩掉它右边的负载
 93     ptr->right = subR;              //右单旋转,ptr成为新根
 94     if(ptr->bf <= 0)        //说明新增结点在左边给了subL
 95         subR->bf = 1;
 96     else
 97         subR->bf = 0;       //说明新增结点在右边给了subR
 98     ptr->bf = 0;
 99 }
100
101 template<class E,class K>
102 void AVLTree<E,K>::RotateRL(AVLNode<E,K> *& ptr)    //先右旋后左旋
103 {
104     AVLNode<E,K> *subR,*subL;
105     subR = ptr->right;
106     subL = ptr;
107     ptr = subR->left;
108     subR->left = ptr->right;    //ptr成为新根前卸掉它右边的负载
109     ptr->right = subR;          //右单旋转,ptr成为新根
110     if(ptr->bf >= 0)
111         subR->bf = 0;
112     else
113         subR->bf = 1;
114     subL->right = ptr->left;    //ptr成为新根前卸掉它的左边的负载
115     ptr->left = subL;           //左单旋转,ptr成为新根
116     if(ptr->bf >= 0)
117         subL->bf = -1;
118     else
119         subL->bf = 0;
120     ptr->bf = 0;
121 }
122 template<class E,class K>
123 bool AVLTree<E,K>::Insert(AVLNode<E,K> *& ptr,E& el)    //在以ptr为根的的树中插入新元素,如果插入成功> ,函数返回true否则返回false
124 {
125     AVLNode<E,K> *pr = NULL,*p = ptr,*q;
126     int d;
127     stack<AVLNode<E,K> * > st;
128     while(p != NULL)                //寻找插入位置
129     {
130         if(el == p->data)           //找到等于el的结点,不插入
131             return false;
132         pr = p;                     //pr是待插入结点的父结点
133         st.push(pr);                //否则用栈记忆查找路径
134         if(el < p->data)
135             p = p->left;
136         else
137             p = p->right;
138     }
139     p = new AVLNode<E,K>(el);       //创建要插入的新结点
140     if(p == NULL)
141     {
142         cerr<<"out of memory"<<endl;
143         exit(1);
144     }
145     if(pr == NULL)      //空树
146     {
147         ptr = p;
148         return true;
149     }
150     if(el < pr->data)
151         pr->left = p;   //左结点插入
152     else
153         pr->right = p;  //右结点插入
154     while(st.empty() == false)
155     {
156         pr = st.top();      //重新平衡化
157         st.pop();           //从栈中退出父结点
158         if(p == pr->left)   //调整父结点的平衡因子
159             pr->bf--;
160         else
161             pr->bf++;
162         if(pr->bf == 0)     //第一种情况,平衡退出
163             break;
164         if(pr->bf == 1 || pr->bf == -1)     //第二种情况,|bf| = 1
165             p = pr;                         //回朔父结点是否存在
166         else                                //第三种情况,|bf| = 2
167         {
168             if(pr->bf == 2)
169             {
170                 if(pr->right->bf > 0)
171                     RotateL(pr);        // \
172                 else
173                     RotateRL(pr);       // >
174             }
175             else
176             {
177                 if(pr->left->bf < 0)
178                     RotateR(pr);        // /
179                 else
180                     RotateLR(pr);       // <
181             }
182             break;
183         }
184     }
185     if(st.empty() == true)      //调整到树的根结点
186         ptr = pr;
187     else
188     {                               //中间重新链接
189         q = st.top();
190         if(q->data > pr->data)
191             q->left = pr;
192         else
193             q->right = pr;
194     }
195     return true;
196 }
197
198
199 template<class E,class K>
200 bool AVLTree<E,K>::Remove(AVLNode<E,K> *& ptr, E k) //在以ptr为根的AVL树中删除关键码为x的结点。如果删> 除成功,函数返回true,同时通过参数el返回被删结点元素,如果删除失败则函数返回false
201 {
202     if(ptr == NULL)
203         return false;
204     AVLNode<E,K> *pr = NULL,*p = ptr,*q;
205     int d,dd = 0;
206     stack<AVLNode<E,K> * > st;
207     while(p != NULL)        //寻找删除位置
208     {
209         if(k == p->data)    //找到等于k的结点,停止搜索
210             break;
211         pr = p;         //pr始终是指向父结点
212         st.push(pr);    //用栈来存储查找的路径
213         if(k < p->data)
214             p = p->left;
215         else
216             p = p->right;
217     }
218     if(p == NULL)
219         return false;
220     if(p->left != NULL && p->right != NULL)
221     {
222         pr = p;
223         st.push(pr);
224         q = p->left;
225         while(q->right != NULL)
226         {
227             pr = q;         //pr是要删除的结点的父结点
228
229             q = q->right;
230         }
231         p->data = q->data;
232         p = q;              //转换要删除的结点
233     }
234
235     if(p->left != NULL)
236         q = p->left;
237     else
238         q = p->right;
239
240     if(pr == NULL)          //要删除的结点为根结点
241         ptr = q;
242     else
243     {
244         if(pr->left == p)   //要删除的结点是父结点的左子树
245             pr->left = q;
246         else
247             pr->right = q;
248         while(!st.empty() )
249         {
250             pr = st.top();
251             st.pop();
252
253             if(pr->left == q)
254                 pr->bf++;
255             else
256                 pr->bf--;
257
258             if(pr->bf == 1 || pr->bf == -1)
259                 break;
260             else if(pr->bf == 0)
261                 continue;
262             else
263             {
264                 if(pr->bf > 0)
265                     q = pr->right;
266                 else
267                     q = pr->left;
268                 if(q->bf == 0)      //单旋转
269                 {
270                     if(pr->bf > 0)
271                     {
272                         RotateL(pr);        // \
273                         //bf
274                         pr->left->bf = 1;
275                         pr->bf = -1;
276                     }
277                     else
278                     {
279                         RotateR(pr);        // /
280                         pr->right->bf = -1;
281                         pr->bf = 1;
282                     }
283                 }
284                 else if(q->bf > 0)
285                 {
286                     if(pr->bf > 0)          // \ //
287                         RotateL(pr);
288                     else                // <
289                         RotateLR(pr);
290                 }
291                 else
292                 {
293                     if(pr->bf < 0)      // /
294                     {
295                         RotateR(pr);
296                     }
297                     else                // >
298                     {
299                         RotateRL(pr);
300                     }
301                 }
302                 break;
303             }
304         }
305         AVLNode<E,K> *ppr = st.top();
306         if(ppr->data > pr->data)
307             ppr->left = pr;
308         else
309             ppr->right = pr;
310     }
311     //2 调整平衡因子
312     delete p;
313     return true;
314 }
315
316 #endif

测试文件

  1 #include"./AVLTree.h"
  2
  3 int main()
  4 {
  5     AVLTree<int,int> avl(0);
  6     int ar[] = {16,3,7,11,9,26,18,14,15};
  7     int n = sizeof(ar)/sizeof(int);
  8     for(int i = 0; i < n; ++i)
  9     {
 10         avl.Insert(ar[i]);
 11     }
 12
 13     avl.Remove(11);
 14
 15     return 0;
 16 }

希望有错误能够指出

    原文作者:AVL树
    原文地址: https://blog.csdn.net/ProgramVAE/article/details/76050336
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞