您的位置:首页 > 其它

AVL树实现(插入删除)

2017-07-25 10:08 501 查看
在计算机科学中,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 }


希望有错误能够指出
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: