【C++第十九章】AVL树
AVL树介绍
尽管已经有了二叉搜索树,但是二叉搜索树存在单支树或近似单支树的情况,这会使二叉搜索树的优势不复存在,所以两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了AVL树,AVL树在二叉搜索树的基础上进行优化,当向二叉树搜索树中插入新结点后,如果能保证每个结点的左右子树高度差的绝对值不超过1,即可降低树的高度,因此减少平均搜索长度。
一棵AVL树具有以下性质:
- 它的左右子树都是AVL树。
- 左右子树高度之差(平衡因子)的绝对值不超过1。
- 如果一棵二叉搜索树高度是平衡的,则它为AVL树,假设有N个结点,那么它的高度可保持在O(log2N),搜索的时间复杂度为O(log2N)。
AVL树结点的定义
在AVL树定义中,我们使用了三叉链,尽管多开了一个指针,但是大大减少了程序的复杂度,插入时可以快速找到父节点从而进行平衡因子判断、调整。
template<class K, class V> //KV模型 struct AVLTreeNode { AVLTreeNode<K, V>* _left; //左孩子 AVLTreeNode<K, V>* _right; //右孩子 AVLTreeNode<K, V>* _parent; //父节点 pair<K, V> _kv; int _bf; //平衡因子 AVLTreeNode(const pair<K, V>& kv) :_left(nullptr) ,_right(nullptr) ,_parent(nullptr) ,_kv(kv) ,_bf(0) {} };
AVL树的插入
插入规则与二叉搜索树规则一致,但是插入后我们需要判断平衡因子的情况。
在插入前,parent的平衡因子会分为三种情况,-1,0,1,而AVL按规则来看,插入后平衡因子会出现两种情况:
- 当插入的cur在左边时,parent的平衡因子bf - 1。
- 当插入的cur在右边时,parent的平衡因子bf + 1。
此时parent的平衡因子可能有三种情况,0,正负1,正负2,那么:
- 如果parent的平衡因子为0,则说明插入前平衡因子为正负1,插入后被调整为0,满足AVL性质,成立