在计算机科学中,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 }
希望有错误能够指出