前言
1.AVL树和红黑树都是通过设计规则对二叉搜索树的缺点进行克服;
2.本文只对规则进行说明,不对为什么这样做做解释;
3.只说明到如何插入节点的深度
AVL树设计规则
1.AVL树中所有子树左右高度差最大为1;
2.左右子树高度的差被称为平衡因子;
(平衡因子 = 右子树高度 - 左子树高度);
3.AVL树基于二叉搜索树;
简易AVL树节点代码
template<class K,class V>
struct AVLTreeNode
{
pair<K, V> _kv;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
//右子树高度 - 左子树高度
//balance factor 中文:平衡因子
//平衡因子是使搜索二叉树平衡的手段,也有其他平衡手段
int _bf;
AVLTreeNode(pair<K, V> kv)
:_kv(kv)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
{
}
};
AVL树插入节点的规则
所有破话平衡的节点插入都可以分类为四种情况对应四种AVL树高度调节方法
第一种:左左插入 -> 右旋
第二种:右右插入 -> 左旋第三种:左右插入-> 左旋 + 右旋 + 平衡因子调整
第四种:右左插入-> 右旋 + 左旋 + 平衡因子调整调整
红黑树设计规则
1.每个节点都有一个颜色,红色或黑色。
2.根节点是黑色的。
3.所有叶节点(NIL节点)都是黑色的。
4.如果一个节点是红色的,则它的两个子节点都是黑色的。
5.从任意节点到其每个叶子的所有路径都包含相同数量的黑色节点。
6.红黑树基于搜索二叉树。
简易红黑树节点代码
enum Colour
{
RED,
BLACK,
};
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data; //一般为键值对
Colour _col;
RBTreeNode(const T& data)
: _data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{
}
};
红黑树插入节点的规则
新插入节点的颜色默认为红色,插入之后针对不同情况对红黑树做调整,使其满足红黑树规则,进而达到平衡搜索二叉树的效果;
约定:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
所有插入节点后会破坏红黑树规则的情况及解决方法如下:
情况一: cur为红,p为红,g为黑,u存在且为红:
解决方式:将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。
情况二: cur为红,p为红,g为黑,u不存在/u存在且为黑
解决方式:
p、g变色–p变黑,g变红
p为g的左孩子,cur为p的左孩子,则进行右单旋转
p、g变色–p变黑,g变红
p为g的右孩子,cur为p的右孩子,则进行左单旋转
情况三: cur为红,p为红,g为黑,u不存在/u存在且为黑
解决方法:
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,
p为g的右孩子,cur为p的左孩子,则针对p做右单旋转。转化为情况二中的问题,后续按情况二中的方法做处理即可。