Lec18 - Red Black Trees
B-Tree的缺点
- 需要维护不同的节点类型
- 需要在2-nodes与3-nodes之间转换
- 需要分裂节点
树旋转
假设我们要构造一棵节点为1,2,3的BST,则我们可以构造出五种可能的BSTs
每种BST的获得是基于插入顺序决定的
更普遍的,对于N个节点的BST,我们可以构造出Catalan(N)种可能的BSTs
而且这些树之间通过旋转(且在\(2n-6\)次旋转内)可以相互转化
rotateLeft
让x作为G的右孩子,实现G为x的新的左孩子,且保持BST的性质
若单纯让G称为P的左孩子,P会连上三棵子树
我们需要将K下的子树移动到G的右子树,这样仍然保留了它小于P且大于G的性质
rotateRight
让x作为P的左孩子,实现P为x的新的右孩子,且保持BST的性质
例
左侧的树可以通过两次旋转得到右侧的树
用处
- 可以缩短或增长一棵树
- 可以保留BST的性质
- 可以使用旋转操作来平衡BST(在\(O(N)\)次移动内)
红黑树
原理
若我们想把一棵2-3树用BST表示,对于3元素节点,处理相对棘手
有一种思路:对一个节点中更小的元素在左下侧创建一个“粘性链接”
并将这个链接设置为红色
我们称这种表示2-3树的形式为左倾红黑树(LLRB)
- LLRBs是正常的BSTs
- 一棵LLRB与一棵2-3树是一一对应的
- 红色链接没有任何特殊行为
树高
- 在LLRB中,每个3nodes节点变成2nodes节点
- 总高为3black+2red=5
- 更通常的,一颗LLRB有不多于其对应2-3树的两倍树高
红黑树的构造
如果先创建2-3树再转换就很麻烦了,我们可以用以下方法构建
- 按BST插入
- 使用0或多次旋转来维持一一对应的关系
- 插入的颜色:我们应该总是插入红色
因为2-3树中新值总是加在叶子节点中
若在叶子右侧插入,造成右倾:我们需要对插入节点的父节点左旋
因为红色链接不应该出现在右侧
若一个节点下插入了两个红色链接:我们可以暂时保持状态
此时在2-3树的表示下为过满,让中间节点上移的状态
- 若存在两次左侧插入:对两个节点的父节点右旋
处理临时的两个红色链接:将两个红色链接置黑,将上方的黑色链接置红
在2-3树中等同于将中间节点上移
- 修复右侧红色链接:有时候颜色反转后会出现单独的右侧红色链接,这时需要左旋
总结
时间复杂度
- LLRB的树高为\(O(\log N)\)
- 插入操作为\(O(\log N)\)(包括插入新节点与旋转、颜色变换)