目录
引子:AVL树是因为什么出现的?
1.AVl树的的特性
2.AVl树的框架
3.AVL树的插入
3.1四种旋转(左单旋、右单旋、左右双旋、右左双旋)
3.1.1左单旋
3.1.2右单旋
3.1.3左右双旋
3.1.4右左双旋
总结
两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年 发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(对树中的结点进行调整),即为AVl树以他们的名字缩写命名也可以叫高度二叉搜索树
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树,它就是AVL树。
如果AVl树有n个结点,其高度可保持在O(logN) ,搜索时间复杂度O(logN),为什么?
答:左右子树高度之差的绝对值不超过1,那么只有最后一层会差一部分的节点;
template
struct AVLtreeNode {//节点构造函数AVLtreeNode(const pair & kv):_left(nullptr),_right(nullptr),_parent(nullptr),_bf(0),_kv(kv){}//节点的成员//三叉链AVLtreeNode * _left;AVLtreeNode * _right;AVLtreeNode * _parent;int _bf;//平衡因子//数据使用库里面的pair类存储的kvpair _kv; }; template class AVLtree {typedef AVLtreeNode Node; public://构造函数AVLtree():_root(nullptr){}//四种旋转void RotateL(Node* parent)void RotateR(Node* parent)void RotateLR(Node* parent)void RotateRL(Node* parent)//插入bool Insert(const pair & kv)//寻找Node* Find(const K& kv) private:Node* _root; };
三叉链是什么?
bool Insert(const pair& kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = _root, *cur = _root;while (cur){//找nulptr,如果已经有这个key了,二叉搜索树的特性不支持冗余,所以返回失败if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else if (cur->_kv.first _right;}else{return false;}}//cur = new Node(kv);//判断孩子在父亲的左边还是右边if (cur->_kv.first > parent->_kv.first){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}while (parent){//影响一条路径所有的祖先if (parent->_right == cur)parent->_bf++;elseparent->_bf--;if (parent->_bf == 0){//左右平衡了不会再影响祖先了break;}if (parent->_bf == 1 || parent->_bf == -1){//当前节点所在子树变了,会影响父亲// 继续往上更新cur = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){//parent所在子树已经不平衡,需要旋转处理一下if (parent->_bf == -2){if (cur->_bf == -1)// 右单旋RotateR(parent);else // cur->_bf == 1RotateLR(parent);}else // parent->_bf == 2{if (cur->_bf == 1)// 左单旋RotateL(parent);else // cur->_bf == -1RotateRL(parent);}break;}else{// 插入节点之前,树已经不平衡了,或者bf出错。需要检查其他逻辑assert(false);}}return true;}
插入整体逻辑:
void RotateR(Node* parent){//轴点的左,孩子节点Node* subL = parent->_left;//孩子节点的右Node* subLR = subL->_right;//我的右当你(轴点)的左parent->_left = subLR;//调整三叉链if (subLR)subLR->_parent = parent;//你(轴点)做我的右subL->_right = parent;//调整三叉链Node* parentParent = parent->_parent;parent->_parent = subL;if (parent == _root){_root = subL;_root->_parent = nullptr;}else{//轴点的父亲新的孩子节点if (parentParent->_left == parent)parentParent->_left = subL;elseparentParent->_right = subL;subL->_parent = parentParent;}subL->_bf = parent->_bf = 0;}
void RotateL(Node* parent){//轴点的右,孩子节点Node* subR = parent->_right;//孩子节点的左Node* subRL = subR->_left;//我的左当你(轴点)的右parent->_right = subRL;//调整三叉链if (subRL){subRL->_parent = parent;}//你(轴点)做我的左subR->_left = parent;Node* parentparent = parent->_parent;parent->_parent = subR;if (parent == _root){if (parentparent->_left == parent)parentparent->_left = subR;elseparentparent->_right = subR;subR->_parent = parentparent;}else{subR->_parent = nullptr;_root = subR;}subR->_bf = parent->_bf = 0;}
void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);// ...平衡因子调节还需要具体分析if (bf == -1){subL->_bf = 0;parent->_bf = 1;subLR->_bf = 0;}else if (bf == 1){parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else if (bf == 0){parent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}else{assert(false);}}
void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);// 平衡因子更新if (bf == 1){subR->_bf = 0;parent->_bf = -1;subRL->_bf = 0;}else if (bf == -1){parent->_bf = 0;subR->_bf = 1;subRL->_bf = 0;}else if (bf == 0){parent->_bf = 0;subR->_bf = 0;subRL->_bf = 0;}else{assert(false);}}