【1】为什么需要平衡二叉树?
矛盾是推进事物向前发展的源动力。
那么平衡二叉树是从哪里来?肯定是有矛盾存在的。请看下面的分析:
【2】什么是平衡二叉树?
平衡二叉树的基本认识:
【3】平衡二叉树的构建原理
平衡二叉树的形成肯定是有一定规律可循的,那么平衡二叉树的“生长”原理是什么呢?
请看程老师下面的构建示例以及详细讲解:
关于平衡二叉树的旋转分为以下四种情况:
【4】平衡二叉树的实现
平衡二叉树的实现代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
Good Good Study, Day Day Up.
顺序 选择 循环 总结