二分查找树 Binary Search Tree
- 若它的左子树不为空,左子树上所有节点的值都小于它的根节点。
- 若它的右子树不为空,右子树上所有的节点的值都大于它的根节点。
- 它的左、右子树也都是二分搜索树。
AVL 树 (二叉平衡搜索树)
什么是 AVL 树
AVL 树 得名于它的发明者G. M. Adelson-Velsky
AVL 树: 二叉平衡搜索树
AVL 树 是在 二叉查找树 的 基础上 对 树 进行平衡,使其 二叉树 和 他的子树,都能高效率的检索
如何判断这个树是否平衡
AVL 树是高度平衡的二叉搜索树,其左子树和右子树的高度差不超过1 (树中的左子树和右子树都是AVL树),维持这个高度之差就要控制它的平衡因子。
左子树 ==减== 右子树 = X < 2
或者
右子树 ==减== 左子树 = X < 2
如果左子树 和 右子树的差 大于 1 那么这个树就不平衡
如果是负数怎么办:abs() 取绝对值
如何让树平衡
旋转的条件
LL (右旋)
- 插入元素在第一个不平衡节点的左侧的左侧
- 如上图所示,根据二叉搜索树的性质他们的大小关系应该是
- 1 < 2 < 3 < 4 < 5 < 8
- 此时我们查看这个树已经不是平衡状态,不平衡节点是 3,5,我们需要对第一个不平衡节点进行 右旋 。由于是加入左树节点时,引起的二叉树不平衡,在 右旋 之后,需要检查左树的数据是否符合二叉查找树的规定,如不符合,将进行从新排列组合
RR (左旋)
-
插入元素在第一个不平衡节点的右侧的右侧
-
-
左旋 与 右旋 相反,因为是插入在 右侧的右侧节点导致树失衡, 失衡节点是 10, 8 此时要进行 左旋 ,左旋 之后同样要对右侧的数据进行从新排列组合
-
LR (左旋 + 右旋)
-
插入元素在第一个不平衡节点的左侧的右侧
-
-
此时首先将第一个不平衡节点进行 左旋
-
-
随后,我们得到 LL 类型的失衡节点,再将第一个失衡节点 右旋
-
RL (右旋 + 左旋)
- 插入元素在第一个不平衡节点的右侧的左侧
- 不平衡节点 25,20。此时首先将第一个不平衡节点进行 右旋
- 随后,我们得到 RR 类型的失衡节点,再将第一个失衡节点进行 左旋
红黑树的定义与性质
红黑树是一种含有红黑节点并且能自平衡的二叉查找树,它满足以下 5 个性质
- 每个节点要么是黑色,要么是红色
- 根节点是黑色
- 每个叶子节点 (NIL)是黑色
- 每个红色节点的两个子节点一定都是黑色
- 任意一节点到每个叶子节点的路径都包含数量相同的黑节点
红黑树是 二叉查找树
树和他的子树满足以下约束:左节点小于父节点,右节点大于父节点。(子树也是一样)
红黑树每个节点多了一个颜色标记位,每个节点非黑即红
红黑树的根节点必须是黑色的,这是硬性规定,你无法推算出根节点不能是红色
每个叶子节点 (NIL)都是黑色的虚节点
- 为什么要有 NIL(叶子) 节点 ,它的作用是什么
- NIL 节点有利于平衡黑色高度,给树一个完美黑平衡
- 什么是树平衡,为什么要刻意的让树平衡
- 因为红黑树是一个二叉查找树,二叉树查找的特点 O(log n ), 即只查找一部分,如果查询的 value 比 根节点大,就去右边找,相反则去左边找,这大大降低了检索的速度。
- 为什么要让这个二叉树平衡,如果不让这个树平衡,而是倾向于左侧,或是 右侧,那这个 二叉树 就会失去平衡,让检索效率降低
- 失去平衡的树
- 失去平衡的树
- 为什么检索的效率会降低
- 此时如果 在上面这个二叉树中查找 一个值 比如 103 ,103 比 根节点大所以在右边的树检索,需要一个一个去对比。那这不就是链表吗?
- 什么是链表,链表的规则是什么
- 链表是一种特殊的存储结构,它是有序的,它的特点在于在 元素中不仅会存储数据,还会存储下一个元素的地址
- 它的缺点就是查找比较麻烦,如果链表中存储的数据比较多,它要在链表中 一个一个元素的去对比,当前元素是不是要查找的元素
如何判断红黑树是否平衡
- 满足以上 五个 条件
如何让红黑树平衡
在插入和删除时,判断节点是否需要变色,或是 旋转(左旋,右旋)
举例:
-
插入 12 根节点为黑色
-
插入 左子节点 1 ,默认为红色
-
插入 9 默认为红色,此时违反两个 规定
- 违反红黑树定义规则
每个红色节点的两个子节点一定都是黑色 - 违反 AVL 树 不平衡
- 违反红黑树定义规则
-
参考 AVL 树的 LR
插入元素在第一个不平衡节点的左侧的右侧- 首先左旋第一个不平衡节点,得到 图4
- 左旋之后还是不平衡,需要再向右旋转,得到 图5
-
由于节点 9 默认是红色,旋转后违反了 红黑树的定义
根节点是黑色,此时将 9 设为黑色 -
插入节点 2 默认红色
-
违反红黑树定义规则
每个红色节点的两个子节点一定都是黑色- 依次向上变色,如果父节点和叔叔节点为红色就变成黑色,如果是黑色就变成红色,依次向上,直至根节点
-
根节点 9 变色后违反了 红黑树定义
根节点是黑色, 所以根节点必须是黑色
解释:
- 红黑树的变色遵循红黑树的定义规则
- 红黑树的旋转遵循 AVL 树的平衡规则
红黑树 和 AVL 树的区别
AVL树的特点
- 和红黑树相比,AVL 树是高度平衡的二叉搜索树,其左子树和右子树的高度差不超过1 (树中的左子树和右子树都是AVL树),无论是执行 插入 还是 删除 操作,只要不满足 AVL 树的高度差 <=1 , 就要通过 旋转 来保持平衡,而旋转操作是比较耗时的,由此得知 AVL 树适合插入 和 删除 比较少,==查询== 比较多的情况。
- AVL 树追求绝对平衡,条件比较苛刻,实现起来比较麻烦,每次插入新节点之后需要旋转的次数不能预知。
- 由于 AVL 树的维护成本比较高,故而实际应用的不多,大多数场景下仅仅是追求局部平衡,并不是完美平衡。
- 相对于 红黑树 ,AVL 树的查找性能更快
红黑树的特点
- 红黑树放弃了完美平衡,而是追求了完美黑平衡(黑色节点是平衡的),相对于 AVL 树来说,红黑树插入最多两次旋转,删除最多三次旋转。红黑树的旋转次数要少,对于 ==插入==,==删除== 比较多的情况下,选择红黑树。
- 红黑树在插入和删除上,优于 AVL 树,AVL 树每次插入,删除都会进行大量的平衡计算,而红黑树为了维持红黑性质所做的红黑节点变色和旋转开销,相对于 AVL 树为了维持平衡度的开销要小。
文章的最后:
- 红黑树的在线演示地址:Red/Black Tree Visualization (usfca.edu)
- 本文结束,写的不好敬请谅解,欢迎各位批评指正