AVL树性质
- 它的左右子树都是AVL树
- 左右子树高度之差的绝对值不超过1(右子树高度 - 左子树高度)(也称为均衡因子)
- 每个节点都有一个均衡因子
- 个别AVL树都是三叉链(左右节点指针和父亲节点指针)
- AVL树高度为 O(logN)
- AVL树的工夫复杂度为O(logN)。
均衡因子的更新准则:
- 如果新增节点在父节点的右边,则父节点的均衡因子减1;顺次向上更新
- 如果新增节点在父节点的左边,则父节点的均衡因子加1;顺次向上更新
- 直到以后节点的均衡因子为0才不向上持续更新了
- 如果均衡因子为-2或2,则须要旋转。而后在判断是否须要持续更新。
AVL树节点的定义形式
template<class K,class V>struct AVLTreeNode //建设节点{ AVLTreeNode<K, V>* _left; AVLTreeNode<K, V>* _right; AVLTreeNode<K, V>* _parent; int _bf; //均衡因子 pair<K, V> _kv; //键值对,存储数据 AVLTreeNode(const pair<K, V>& kv) //构造函数 :_left(nullptr) ,_right(nullptr) ,_parent(nullptr) ,_bf(0) ,_kv(kv) {}};
AVL树的四种旋转形式
为什么要旋转
- 当插入一个节点时,直接插入可能会导致均衡被毁坏(插入节点的所有先人节点的均衡因子可能会扭转)
- 这时就须要将数据进行旋转
- 例如:当插入 30 节点时,这个树就不是AVL树了,所以将其进行旋转,失去左边的AVL树。
右单旋
右单旋代码实现
//右单旋 void RotateR(Node* parent) { Node* subL = parent->_left; Node* subLR = subL->_right; Node* parent_parent = parent->_parent; parent->_left = subLR; if (subLR) subLR->_parent = parent; subL->_right = parent; parent->_parent = subL; if (parent == _root) { _root = subL; _root->_parent = nullptr; } else { if (parent_parent->_left == parent) parent_parent->_left = subL; else parent_parent->_right = subL; subL->_parent = parent_parent; } subL->_bf = 0; parent->_bf = 0; }
左单旋
左单旋代码实现
//左单旋 void RotateL(Node* parent) { Node* subR = parent->_right; Node* subRL = subR->_left; Node* parent_parent = parent->_parent; parent->_right = subRL; if (subRL) subRL->_parent = parent; subR->_left = parent; parent->_parent = subR; if (parent == _root) { _root = subR; subR->_parent = nullptr; } else { if (parent_parent->_left == parent)parent_parent->_left = subR; else parent_parent->_right = subR; subR->_parent = parent_parent; } subR->_bf = 0; parent->_bf = 0; }
左右双旋
左右双旋代码实现
//左右双旋 void LRrotate(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) { subL->_bf = -1; parent->_bf = 0; subLR->_bf = 0; } else if (bf == 0) { subL->_bf = 0; parent->_bf = 0; subLR->_bf = 0; } else { assert(false); } }
右左双旋
原理同上。
//右左双旋 void RLrotate(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); } }
源码地址
gitee地址:https://gitee.com/BJFyfwl/Lin...