单独开一章节介绍 RotateL 、 RotateR 及更复杂的 LR 和 RL 型旋转,更多是为了红黑树的旋转部分做铺垫;由于 AVL 树和红黑树发生旋转的判断标准不同 —— 分别为平衡因子和节点的颜色,两棵树左旋和右旋的在细节上会有一些差异,但从整体来看,二者的精神一致。
定义节点
template <class K, class V>struct AVLTreeNode{AVLTreeNode* _left;AVLTreeNode* _right;pair<K, V> _kv;AVLTreeNode* _parent;int _bf;AVLTreeNode(const pair<K, V>& kv):_left(nullptr),_right(nullptr),_kv(kv),_parent(nullptr),_bf(0){}};
关于如何快速记忆什么时候为左旋、右旋、或左右旋、或右左旋,有一个小技巧:
当左树更高,需要向右调整高度,此时右旋;
当右树更高,需要向左调整高度,此时左旋 … …
一、新节点插入较高左子树的左侧 —— 引发右单旋
void RotateR(Node* parent){Node* ppnode = parent->_parent;Node* subLeft = parent->_left;Node* subLeftR = subLeft->_right;parent->_left = subLeftR;if (subLeftR)subLeftR->_parent = parent;subLeft->_right = parent;parent->_parent = subLeft;if (ppnode == nullptr){_root = subLeft;subLeft->_parent = nullptr;}else {subLeft->_parent = ppnode;}// 调整平衡因子parent->_bf = 0;subLeft->_bf = 0;}
二、新节点插入较高右子树的右侧 —— 引发左单旋
void RotateL(Node* parent){Node* ppnode = parent->_parent;Node* subRight = parent->_right;Node* subRightL = subRight->_left;parent->_right = subRight;if (subRight)subRight->_parent = parent;subRight->_left = parent;parent->_parent = subRight;if (ppnode == nullptr){_root = subRight;subRight->_parent = nullptr;}else {subRight->_parent = ppnode;}parent->_bf = 0;subRight->_bf = 0;}
三、新节点插入较高左子树的右侧 —— 引发左右双旋
根据旋转之前 subLeftR
的平衡因子,来决定旋转后各节点的平衡因子。
void RotateLR(Node* parent){Node* subLeft = parent->_left;Node* subLeftR = subLeft->_right;int bf = subLeftR->_bf; // 记录旋转前的平衡因子RotateL(subLeft);RotateR(parent);if (bf == -1){parent->_bf = 1;subLeft->_bf = subLeftR->_bf = 0;}else if (bf == 1){subLeft->_bf = -1;parent->_bf = subLeftR->_bf = 0;}else {parent->_bf = subLeft->_bf = subLeftR->_bf = 0;}}
四、新节点插入较高右子树的左侧 —— 引发右左双旋
void RotateRL(Node* parent){Node* subRight = parent->_right;Node* subRightL = subRight->_left;int bf = subRightL->_bf;RotateR(subRight);RotateL(parent);if (bf == 1){parent->_bf = -1;subRight->_bf = subRightL->_bf = 0;}else if (bf == -1){subRight->_bf = 1;parent->_bf = subRightL->_bf = 0;}else {parent->_bf = subRight->_bf = subRightL->_bf = 0;}}