二叉平衡树
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 }
重点:
- 左旋和右旋的含义:举例子,左旋就是让node节点的右子节点,成为node的父节点,node为其左节点
- AVL调整的过程在,先按二叉排序树的插入,然后往上递归父节点,重新计算平衡值,如果node平衡值Abs绝对值大于1,说明不平衡,再对比其子节点的平衡值,确认是LL LR RL RR哪种类型!
浙公网安备 33010602011771号