AVL树的四种旋转
AVL树是c++中很常用的数据结构,其独有的特点使得其增删查改的效率都是logn级别。AVL树中最核心的是四种旋转方式,我将从代码入手去分析四种旋转的特点,具体图例就不画了。
// 右单旋void RotateR(Node* parent)//画图解释,最为直观。{Node* subL = parent->_pLeft;//记录左子树顶点位置Node* subLR = subL->_pRight;//记录顶点位置的右节点,可能为nullptrparent->_pLeft = subLR;//将目前节点的左节点设置为刚刚记录的subLR,不违背搜索二叉树的原则if (subLR)//如果subLR是空的话,pass。如果不是,那就让它认parent作爹{subLR->_pParent = parent;}subL->_pRight = parent;//让subL的右儿子成为parentparent->_pParent = subL;//让parent认subL作爹if (parent == _Proot)//如果这个parent是根,也是parent没爹{subL->_pParent = nullptr;//因为变换以后,subL就是根了,那他也就没爹了_root = subL;}else{subL->_pParent = parent->_pParent;//如果parent有爹,那就让subL换个爹if (parent->_pParent->_pLeft == parent)//这串if/else的逻辑总体用于判断parent到底是他爹的左孩子还是右孩子{parent->_pParent->_pLeft = subL;}else if (parent->_pParent->_pRight == parent){parent->_pParent->_pRight = subL;}}subL->_bf = 0;//默认调整以后这个左孩子和parent就是圆满的了parent->_bf = 0;}
// 左单旋
void RotateL(Node* parent)
{Node* subR = parent->_pRight;//Node* subRL = subR->_pLeft;parent->_pRight = subRL;if (subRL){subRL->_pParent = parent;}subR->_pLeft = parent;if (parent == _Proot){subR->_pParent = nullptr;parent->_pParent = subR;}else{subR->_pParent = parent->_pParent;if (parent->_pParent->_pLeft == parent){parent->_pParent->_pLeft = subR;}else if (parent->_pParent->_pRight == parent){parent->_pParent->_pRight = subR;}}subR->_bf = 0;parent->_bf = 0;
}
// 右左双旋void RotateRL(Node* parent){Node* subR = parent->_pRight;//记录parent右子树的地址。Node* subRL = subR->_pLeft;//记录subR左子树的地址。int bf = subRL->_bf;//记录subRL的平衡因子,这在后面判断会有大用处。RotateR(parent->_pRight);//双旋的本质就是调用两次单旋转,先调用一次右单旋,再调用一次左子树RotateL(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 {assert(false);//如果调到了这里,表示之前bf的相关代码有写错的}}
// 左右双旋void RotateLR(Node* parent){Node* subL = parent->_pLeft;Node* subLR = SubL->_pRight;int bf = subLR->_bf;RotateL(parent->_pLeft);RotateR(parent);if (bf == 0){parent->_bf = 0;subL->_pLeft = 0;subLR->_pLeft = 0;}else if (bf == 1){parent->_bf = 0;subL->_pLeft = -1;subLR->_pLeft = 0;}else if (bf == -1){parent->_bf = 1;subL->_pLeft = 0;subLR->_pLeft = 0;}else {assert(false);}}