关于AVL树的讲解
绝对值
不超过1 (-1/0/1)//AVL 树的节点
template
struct AVLTreeNode
{pair _kv;AVLTreeNode* _left;AVLTreeNode* _right;AVLTreeNode* _parent;//左右子数的高度差int _bf;AVLTreeNode(const pair& kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr), _bf(0){}
};
bool Insert(const pair& kv){// 1、搜索树的规则插入// 2、看是否违反平衡规则,如果违反就需要处理:旋转if (_root == nullptr){_root = new Node(kv);_root->_bf = 0;return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;// ...// 更新平衡因子while (parent) // 最远要更新根{if (cur == parent->_right){parent->_bf++;}else{parent->_bf--;}// 是否继续更新?if (parent->_bf == 0) // 1 or -1 -》 0 插入节点填上矮的那边{// 高度不变,更新结束break;}else if (parent->_bf == 1 || parent->_bf == -1)// 0 -》 1 或 -1 插入节点导致一边变高了{// 子树的高度变了,继续更新祖先cur = cur->_parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2)// -1 or 1 -》 2 或 -2 插入节点导致本来高一边又变高了{// 子树不平衡 -- 需要旋转处理if (parent->_bf == 2 && cur->_bf == 1) // 左单旋{RotateL(parent);}else if (parent->_bf == -2 && cur->_bf == -1) // 右单旋{RotateR(parent);}else if (parent->_bf == -2 && cur->_bf == 1) // 左右双旋{RotateLR(parent);}else if (parent->_bf == 2 && cur->_bf == -1) // 右左双旋{RotateRL(parent);}break;}else{// 插入之前AVL就存在不平衡子树,|平衡因子| >= 2的节点assert(false);}}return true;}
当一个树左右高度差绝对值大于1
的时候就要进行旋转
这是一个简单的示范:
图片演示
(我自己纯手画):
代码:
void RotateL(Node* parent)//左单旋{Node* SubR = parent->_right;Node* SubRL = SubR->_left;parent->_right = SubRL;if (SubRL){SubRL->_parent = parent;}Node* ppNode = parent->_parent;SubR->_left = parent;parent->_parent = SubR;if (_root == parent){_root = SubR;_root->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = SubR;}else{ppNode->_right = SubR;}SubR->_parent = ppNode;}//旋转结束更新平衡因子parent->_bf = 0;SubR->_bf = 0;}
图片演示
(我纯手画)
代码:
void RotateR(Node* parent)//右单旋{Node* SubL = parent->_left;Node* SubLR = SubL->_right;parent->_left = SubLR;if (SubLR){SubLR->_parent = parent;}Node* ppNode = parent->_parent;SubL->_right = parent;parent->_parent = SubL;if (_root == parent){_root = SubL;_root->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = SubL;}else{ppNode->_right = SubL;}SubL->_parent = ppNode;}//旋转结束更新平衡因子parent->_bf = 0;SubL->_bf = 0;}
图片演示
(我纯手画):
parent节点平衡因子和subL节点的平衡因子都与subLR有关
subLR | parent | subL |
---|---|---|
0 | 0 | 0 |
1 | 0 | -1 |
-1 | 1 | 0 |
代码:
void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);// 更新平衡因子if (bf == 0){parent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}else if (bf == 1){parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else if (bf == -1){parent->_bf = 1;subL->_bf = 0;subLR->_bf = 0;}else{// subLR->_bf旋转前就有问题assert(false);}}
图片演示
(我自己纯手画):
e?)]
parent节点平衡因子和subR节点的平衡因子都与subRL有关
subRL | parent | subR |
---|---|---|
0 | 0 | 0 |
1 | -1 | 0 |
-1 | 0 | 1 |
代码:
void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){subRL->_bf = 0;parent->_bf = 0;subR->_bf = 0;}else if (bf == 1){subRL->_bf = 0;parent->_bf = -1;subR->_bf = 0;}else if (bf == -1){subRL->_bf = 0;parent->_bf = 0;subR->_bf = 1;}else{// subLR->_bf旋转前就有问题assert(false);}}
一起加油