1、AVL树简介
AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。
- 它的子树都是AVL树
- 左右子树高度插(平衡因子)的绝对值不超过1
AVL树还是一个搜索二叉树,只不过因为普通的搜索二叉树有可能变成单只树,这样就使查找效率非常的低。我们就给普通的搜索二叉树增加了一个平衡因子来使AVL左右子树的高度差的绝对值不超过1
template<class K,class V>
struct AVLTreeNode
{AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent; pair<K, V> _kv; // 存储的键对int _bf; // balance factorAVLTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _bf(0){}
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const pair<K, V>& kv);bool IsBalance();void InOrder();void Height();private:void RotateL(Node* parent); //左旋转void RotateR(Node* parent); //右旋转void RotateRL(Node* parent); //右左旋转void RotateLR(Node* parent); //左右旋转bool _IsBalance(Node* root);void _InOrder(Node* root);int _Height(Node* root);Node* _root = nullptr;
};
2、AVL树的插入
- AVL树的插入前面和搜索二叉树的插入一模一样,只不过我们要注意平衡因子
- 因为AVL树保持平衡是要平衡因子的绝对值不超过1,而插入会使平衡因子改变,所以我们也要要相应的旋转,使平衡因子的绝对值不超过一,我们又有几种情况
- 假如以pParent为根的子树不平衡,即pParent的平衡因子为2或者-2,分以下情况考虑
- parent的平衡因子为2,说明parent的右子树高,设parent的右子树的根为subR,当subR的平衡因子为1时,执行左单旋。当subR的平衡因子为-1时,执行右左双旋
- parent的平衡因子为-2,说明parent的左子树高,设parent的左子树的根为subL,当subL的平衡因子为-1是,执行右单旋。当subL的平衡因子为1时,执行左右双旋
- 旋转完成后,原parent为根的子树个高度降低,已经平衡,不需要再向上更新
template<class K, class V>
bool AVLTree<K, V>::Insert(const pair<K, V>& kv)
{if (_root == nullptr){_root = new Node(kv);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->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;// 更新平衡因子while (parent){if (cur == parent->_right){parent->_bf++;}else{parent->_bf--;}if (parent->_bf == 1 || parent->_bf == -1){// 继续更新parent = parent->_parent;cur = cur->_parent;}else if (parent->_bf == 0){break;}else if (parent->_bf == 2 || parent->_bf == -2){// 需要旋转处理 -- 1、让这颗子树平衡 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);}else{assert(false);}break;}else{assert(false);}}return true;
}
2.1、左单旋
- subRL变成parent的右子树
- parent变成subR的左子树
- subR变成新根
- 更新平衡因子
template<class K, class V>
void AVLTree<K, V>::RotateL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;subR->_left = parent;Node* parentParent = parent->_parent;parent->_parent = subR;if (subRL)subRL->_parent = parent;if (_root == parent){_root = subR;subR->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subR;}else{parentParent->_right = subR;}subR->_parent = parentParent;}parent->_bf = subR->_bf = 0;
}
2.2、右单旋
60为parent,30为subL,b为subLR
- subLR变成parent的左子树
- parent变成subL的右子树
- subL变成新根
- 更新平衡因子
template<class K, class V>
void AVLTree<K, V>::RotateR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;Node* parentParent = parent->_parent;subL->_right = parent;parent->_parent = subL;if (_root == parent){_root = subL;subL->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subL;}else{parentParent->_right = subL;}subL->_parent = parentParent;}subL->_bf = parent->_bf = 0;
}
2.3、左右双旋
先对30进行左单旋,先对90右单旋
template<class K, class V>
void AVLTree<K, V>::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 = subL->_bf = subLR->_bf = 0;}else if (bf == -1){parent->_bf = 1;subLR->_bf = 0;subL->_bf = 0;}else if (bf == 1){parent->_bf = 0;subLR->_bf = 0;subL->_bf = -1;}else{assert(false);}
}
2.3、右左双旋
先对90进行右单旋,先对30左单旋
template<class K, class V>
void AVLTree<K, V>::RotateRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){// subRL自己就是新增parent->_bf = subR->_bf = subRL->_bf = 0;}else if (bf == -1){// subRL的左子树新增parent->_bf = 0;subRL->_bf = 0;subR->_bf = 1;}else if (bf == 1){// subRL的右子树新增parent->_bf = -1;subRL->_bf = 0;subR->_bf = 0;}else{assert(false);}
}
3、AVL树的性能
AVL树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1,和红黑树相比,它是严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过1)。不管我们是执行插入还是删除操作,只要不满足上面的条件,就要通过旋转来保持平衡,而旋转是非常耗时的,由此我们可以知道AVL树适合用于插入删除次数比较少,但查找多的情况。
如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合
4、实现
#include<assert.h>template<class K,class V>
struct AVLTreeNode
{AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent; pair<K, V> _kv; // 存储的键对int _bf; // balance factorAVLTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _bf(0){}
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const pair<K, V>& kv);bool IsBalance();void InOrder();void Height();private:void RotateL(Node* parent); //左旋转void RotateR(Node* parent); //右旋转void RotateRL(Node* parent); //右左旋转void RotateLR(Node* parent); //左右旋转bool _IsBalance(Node* root);void _InOrder(Node* root);int _Height(Node* root);Node* _root = nullptr;
};template<class K, class V>
bool AVLTree<K, V>::Insert(const pair<K, V>& kv)
{if (_root == nullptr){_root = new Node(kv);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->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;// 更新平衡因子while (parent){if (cur == parent->_right){parent->_bf++;}else{parent->_bf--;}if (parent->_bf == 1 || parent->_bf == -1){// 继续更新parent = parent->_parent;cur = cur->_parent;}else if (parent->_bf == 0){break;}else if (parent->_bf == 2 || parent->_bf == -2){// 需要旋转处理 -- 1、让这颗子树平衡 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);}else{assert(false);}break;}else{assert(false);}}return true;
}template<class K, class V>
void AVLTree<K, V>::RotateL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;subR->_left = parent;Node* parentParent = parent->_parent;parent->_parent = subR;if (subRL)subRL->_parent = parent;if (_root == parent){_root = subR;subR->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subR;}else{parentParent->_right = subR;}subR->_parent = parentParent;}parent->_bf = subR->_bf = 0;
}template<class K, class V>
void AVLTree<K, V>::RotateR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;Node* parentParent = parent->_parent;subL->_right = parent;parent->_parent = subL;if (_root == parent){_root = subL;subL->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subL;}else{parentParent->_right = subL;}subL->_parent = parentParent;}subL->_bf = parent->_bf = 0;
}template<class K, class V>
void AVLTree<K, V>::RotateRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){// subRL自己就是新增parent->_bf = subR->_bf = subRL->_bf = 0;}else if (bf == -1){// subRL的左子树新增parent->_bf = 0;subRL->_bf = 0;subR->_bf = 1;}else if (bf == 1){// subRL的右子树新增parent->_bf = -1;subRL->_bf = 0;subR->_bf = 0;}else{assert(false);}
}template<class K, class V>
void AVLTree<K, V>::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 = subL->_bf = subLR->_bf = 0;}else if (bf == -1){parent->_bf = 1;subLR->_bf = 0;subL->_bf = 0;}else if (bf == 1){parent->_bf = 0;subLR->_bf = 0;subL->_bf = -1;}else{assert(false);}
}template<class K, class V>
void AVLTree<K, V>::InOrder()
{_InOrder(_root);cout << endl;
}template<class K, class V>
void AVLTree<K, V>::_InOrder(Node* root)
{if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << " ";_InOrder(root->_right);
}template<class K, class V>
bool AVLTree<K, V>::IsBalance()
{return _IsBalance(_root);
}template<class K, class V>
int AVLTree<K, V>::_Height(Node* root)
{if (root == nullptr)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}template<class K, class V>
void AVLTree<K, V>::Height()
{cout << _Height(_root) << endl;
}template<class K, class V>
bool AVLTree<K,V>::_IsBalance(Node* root)
{if (root == nullptr)return true;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);if (rightHeight - leftHeight != root->_bf){cout << root->_kv.first << "平衡因子异常" << endl;return false;}return abs(rightHeight - leftHeight) < 2&& _IsBalance(root->_left)&& _IsBalance(root->_right);
}