二叉平衡树

  1 #include "MyAVLTree.h"
  2 #include <iostream>
  3 
  4 
  5 MyAVLTree::MyAVLTree()
  6 {
  7     root_ = nullptr;
  8 }
  9 
 10 
 11 MyAVLTree::~MyAVLTree()
 12 {
 13 }
 14 
 15 
 16 void MyAVLTree::UpdateDepth(MyTNode *node)
 17 {
 18     if (node == nullptr)
 19         return;
 20     int l_depth = node->lchild == nullptr ? 0 : node->lchild->depth;
 21     int r_depth = node->rchild == nullptr ? 0 : node->rchild->depth;
 22     node->depth = (l_depth > r_depth ? l_depth : r_depth) + 1;
 23 }
 24 
 25 
 26 int MyAVLTree::GetBF(MyTNode *node)
 27 {
 28     int l_depth = node->lchild==nullptr?0: node->lchild->depth;
 29     int r_depth = node->rchild == nullptr ? 0 : node->rchild->depth;
 30     return l_depth - r_depth;
 31 }
 32 
 33 //左旋转本质:
 34 //node变成其右子节点的左子节点
 35 //node的右子节点的左子节点变成node的右子节点
 36 MyTNode* MyAVLTree::L_Rotate(MyTNode*node)
 37 {
 38     //第一步 交换N和R的值
 39     auto r_child = node->rchild;
 40     {
 41         auto tmp = node->value;
 42         node->value = r_child->value;
 43         r_child->value = tmp;
 44     }
 45 
 46     //第二步 N和R指针互换
 47     {
 48         auto tmp = r_child;
 49         r_child = node;
 50         node = tmp;
 51     }
 52 
 53     //第三步  做空N节点  r_child与r_child->r_child->r_child直连 跳过node
 54     r_child->rchild = node->rchild;
 55     if(node->rchild!=nullptr)
 56         node->rchild->parent = r_child;
 57 
 58     //第四步  node的左节点变成node的右节点
 59     node->rchild = node->lchild;
 60 
 61     //第五步 如果r_child拥有左节点X,node的左节点赋值为X
 62     node->lchild = r_child->lchild;
 63     if (r_child->lchild != nullptr)
 64     {        
 65         r_child->lchild->parent = node;
 66     }
 67 
 68     //第六步 r_child左节点赋值为node
 69     r_child->lchild = node;
 70     node->parent = r_child;
 71     return node;
 72 }
 73 
 74 
 75 MyTNode* MyAVLTree::R_Rotate(MyTNode*node)
 76 {
 77     //auto parent = node->parent;
 78     auto l_child = node->lchild;
 79 
 80     //第一步交换 node 和其左孩子的值
 81     //这个时候node变成了原来的左孩子   左孩子l_child变成了node
 82     //下面操作node,其实已经是新的node了,即为l_child
 83     auto tmp = node->value;
 84     node->value = l_child->value;
 85     l_child->value = tmp;
 86     {
 87         auto tmp = node;
 88         node = l_child;
 89         l_child = tmp;
 90     }
 91     //
 92     if (l_child->lchild != nullptr)
 93     {
 94         l_child->lchild = node->lchild;
 95         if(node->lchild!=nullptr)
 96             node->lchild->parent = l_child;
 97     }
 98 
 99     //
100     
101     node->lchild = node->rchild;
102     node->rchild = l_child->rchild;
103     if (l_child->rchild != nullptr)
104     {
105         l_child->rchild->parent = node;
106         l_child->rchild = node;
107     }
108     node->parent = l_child;
109     l_child->rchild = node;
110     return node;
111 }
112 
113 void MyAVLTree::AVLTree(MyTNode *node)
114 {
115     int bf = 0;//平衡因子
116     while (node != nullptr)
117     {
118         UpdateDepth(node);
119         bf = GetBF(node);
120         //说明已经不平衡了!!!!
121         if (bf > 1 || bf < -1)
122         {
123             //左子树高
124             if (bf > 1)
125             {
126                 int l_bf = GetBF(node->lchild);
127                 if (l_bf >= 0)//LL型
128                 {
129                     //需要重新计算深度
130                     node = R_Rotate(node);
131                     continue;
132                 }
133                 else//LR型
134                 {
135                     node = L_Rotate(node->lchild);
136                     //R_Rotate(node);
137                     //node = tmp;
138                     continue;
139                 }
140             }
141             if (bf < -1)
142             {
143                 int l_bf = GetBF(node->rchild);
144                 if (l_bf <=0)//RR型
145                 {
146                     //需要重新计算深度
147                     node = L_Rotate(node);
148                     continue;
149                 }
150                 else//RL型
151                 {
152                     //需要重新计算深度
153                     node = R_Rotate(node->rchild);
154                     continue;
155                 }
156             }
157             //需要调整
158         }
159         node = node->parent;
160     }
161 }
162 
163 
164 void MyAVLTree::Del(int val, MyTNode*node)
165 {
166     if(node == nullptr)
167         node = Search( val, root_);
168 
169     if (node == nullptr)
170         return;
171 
172     //没有子树 直接删除
173     if (node->lchild == nullptr && node->rchild == nullptr)
174     {
175         //调整node parent
176         if (node->parent->lchild == node)
177         {
178             node->parent->lchild = nullptr;
179         }
180         else
181             node->parent->rchild = nullptr;
182 
183         AVLTree(node->parent);
184 
185         delete node;
186         node = nullptr;
187 
188 
189         return;
190     }
191     else if (node->rchild == nullptr)
192     {
193         //需要从node_parent开始调整
194         auto node_parent = node->parent;
195         if (node->parent->lchild == node)
196         {
197             node->parent->lchild = node->lchild;
198             node->lchild->parent = node->parent;
199         }
200         else
201         {
202             node->parent->rchild = node->lchild;
203             node->lchild->parent = node->parent;
204         }
205 
206         AVLTree(node->parent);
207 
208         delete node;
209         node = nullptr;
210 
211         return;
212     }
213     else if (node->lchild == nullptr)
214     {
215         //需要从node_parent开始调整
216         auto node_parent = node->parent;
217         if (node->parent->lchild == node)
218         {
219             node->parent->lchild = node->rchild;
220             node->rchild->parent = node->parent;
221         }
222         else
223         {
224             node->parent->rchild = node->rchild;
225             node->rchild->parent = node->parent;
226         }
227 
228         AVLTree(node->parent);
229         delete node;
230         node = nullptr;
231 
232         return;
233     }
234     else
235     {
236         //删除的节点node存在左右两颗子树
237         auto forward_node = node->lchild;
238         //使用复制删除  找到前驱(左子树中,一直往右下方寻找,找到没有右节点的节点,替代node)
239         while (forward_node->rchild != nullptr)
240         {
241             forward_node = forward_node->rchild;
242         }
243         node->value= forward_node->value;
244         return Del(-1, forward_node);
245     }
246 }
247 
248 MyTNode *MyAVLTree::Search(int val, MyTNode *node)
249 {
250     if (node == nullptr)
251         return nullptr;
252     if (node->value == val)
253         return node;
254     if (node->value > val)
255     {
256         return Search( val, node->lchild);
257     }
258     else
259         return Search( val, node->rchild);
260 }
261 
262 void MyAVLTree::Insert(int val)
263 {
264     //返回插入节点所在位置,按二叉排序树的简单插入
265     MyTNode* node = InsertVal(root_, root_, val);
266     //更新深度
267     UpdateDepth(node);
268     //二叉树的平衡调整,里面会递归更新每个节点的深度
269     AVLTree(node);
270 }
271 
272 void MyAVLTree::PrintLastOrder(MyTNode *node)
273 {
274     if (node == nullptr)
275         return;
276     
277     PrintLastOrder(node->lchild);
278     PrintLastOrder(node->rchild);
279     std::cout << node->value << std::endl;
280 }
281 void MyAVLTree::PrintMidOrder(MyTNode *node)
282 {
283     if (node == nullptr)
284         return;
285 
286     std::cout << node->value << std::endl;
287     PrintMidOrder(node->lchild);
288     PrintMidOrder(node->rchild);
289 }
290 
291 void MyAVLTree::PrintPreOrder(MyTNode *node)
292 {
293     if (node == nullptr)
294         return;
295     PrintPreOrder(node->lchild);
296     std::cout << node->value << std::endl;
297     PrintPreOrder(node->rchild);
298 }
299 
300 MyTNode* MyAVLTree::InsertVal(MyTNode* &node, MyTNode* &parent, int val)
301 {
302     if(node == nullptr)
303     {
304         if (parent == nullptr)
305         {
306             node = new MyTNode();
307             node->value = val;
308             node->parent = nullptr;
309             return node;
310         }
311         node = new MyTNode();
312         node->value = val;        
313         node->parent = parent;
314         return node;
315     }
316     if (node->value > val)
317     {
318         return InsertVal(node->lchild, node, val);
319     }
320     else
321     {
322         return InsertVal(node->rchild, node, val);
323     }
324 }

 

重点:

  1. 左旋和右旋的含义:举例子,左旋就是让node节点的右子节点,成为node的父节点,node为其左节点
  2. AVL调整的过程在,先按二叉排序树的插入,然后往上递归父节点,重新计算平衡值,如果node平衡值Abs绝对值大于1,说明不平衡,再对比其子节点的平衡值,确认是LL LR RL RR哪种类型!
posted @ 2019-02-28 11:30  仙7道  阅读(167)  评论(0)    收藏  举报