题意:
本题你需要处理AVL树的四种情况,分别是RR、RL、LL和LR。
注意:本题不仅需要正确设置子节点,也需要你正确处理父节点,还需要你正确维护height
也就是树高字段,判分模板会根据你的height
来判断平衡是否满足要求。
思路:
①对于RR、LL型。 以RR型为例,被破坏节点记为node,其右儿子记为t。首先先将node右儿子变为t的左儿子,若t的左儿子非空,将其父节点设为node,再将t的左儿子指向node。然后先将t的父节点由原本的node变为node的父节点,再将node的父节点变为t,在做完这两个父节点的转化后,容易忘记对t现在的父节点的调整。对t的父节点进行一个判空,若不为空则将其左儿子或者右儿子指向t。最后再对t和node的高度调整一下即可。LL型与RR相似,在此不赘述。
②对于LR、RL型。只需借用RR、LL型旋转即可,这里以RL为例。先将t作为被破坏点传入LL型旋转中,LL旋转完后则会变成以node为被破坏点的RR型,这时将node传入RR型旋转函数中即可。
源码:
#include <algorithm>
//struct BTreeNode{
// int value{0};
// int height{0};
// BTreeNode* parent{nullptr};
// BTreeNode* left_child{nullptr};
// BTreeNode* right_child{nullptr};
// BTreeNode( int value ){
// this->value = value;
// }
// BTreeNode(){
// this->value = 0;
// }
//};
//
int h(BTreeNode * node) { //获取树高度函数
if (!node)
return -1;
else
return node->height;
}
void rotate_rr(BTreeNode* node) {
if (!node) return; //对树判空
BTreeNode* t = node->right_child;
node->right_child = t->left_child;
if (t->left_child)
t->left_child->parent = node;
t->parent = node->parent;
if (t->parent)
if (t->parent->left_child == node) //将t父节点的左或右儿子指向node
t->parent->left_child = t;
else
t->parent->right_child = t;
node->parent = t;
t->left_child = node;
node->height = max(h(node->left_child), h(node->right_child)) + 1; //获取高度
t->height = max(h(t->left_child), h(t->right_child)) + 1;
}
void rotate_ll(BTreeNode* node) {
if (!node) return; //对树判空
BTreeNode* t = node->left_child;
node->left_child = t->right_child;
if (t->right_child)
t->right_child->parent = node;
t->parent = node->parent;
if (t->parent)
if (t->parent->left_child == node)//将t父节点的左或右儿子指向node
t->parent->left_child = t;
else
t->parent->right_child = t;
node->parent = t;
t->right_child = node;
node->height = max(h(node->left_child), h(node->right_child)) + 1;
t->height = max(h(t->left_child), h(t->right_child)) + 1;
}
void rotate_rl(BTreeNode* node) {
BTreeNode* t = node->right_child;
rotate_ll(t);
rotate_rr(node);
}
void rotate_lr(BTreeNode* node) {
BTreeNode* t = node->left_child;
rotate_rr(t);
rotate_ll(node);
}
ps:对于RR、LL型,以RR型为例。不管t的左儿子是否空,都要先将其成为node的右儿子,然后再判空,来决定是否要调整t左儿子的父节点;在t的父节点调整为node的父节点后,还要对调整后的t父节点判空,来决定是否要调整其左或右儿子指向t。