二叉查找树
二叉树是一个空链接,或者是一个有左右两个链接的节点,每个链接都指向一颗子二叉树
二叉查找树(BST)是一颗二叉树,并且每个节点的值都大于等于其左子树中的所有节点的值,小于等于右子树的所有节点的值
二叉查找树有一个重要的性质就是它的中序遍历结果递增排序
二叉查找树的数据结构
1 | public class BST<Key extends Comparable<Key>, Value> { |
get()
- 如果树是空的,则查找未命中
- 如果被查找的键和根节点的键相等,查找命中
- 否则递归地在子树中查找:如果被查找的键较小就在左子树中查找,较大就在右子树中查找
1 | public Value get(Key key) { |
put()
当插入的键不存在于树中,需要创建一个新节点,并且更新上层节点的链接使得该节点正确链接到树中
1 | public void put(Key key, Value val) { |
分析
最好情况(完全二叉树):每条空链接和根节点的距离都是logN
最坏情况(单边):树的高度为N
floor()
floor(key):小于等于key的最大值
- 如果键小于根节点的键,那么floor(key)一定在左子树中
- 如果键大于根节点的键,那么先判断右子树中是否存在floor(key)
- 存在就找到,不存在就判断根节点
1 | public Key floor(Key key) { |
rank()
- 如果键和根节点的值相等,返回左子树的节点数
- 如果小于,递归计算在左子树中的排名
- 如果大于,递归计算在右子树总的排名,并加上左子树的节点数和根节点
1 | public int rank(Key key) { |
min()
1 | private Node min(Node x) { |
deleteMin()
1 | public void deleteMin() { |
delete()
- 如果待删除的节点只有一个子树,那么只需要让指向待删除节点的链接指向唯一的子树即可
- 否则,让右子树的最小节点替换该节点
1 | public void delete(Key key) { |
keys()
利用二叉查找树中序遍历的结果为递增的特点
1 | public Iterable<Key> keys(Key lo, Key hi) { |
2-3查找树
2-3查找树中引入了2-节点和3-节点,目的是为了让树平衡,一颗完美平衡的2-3查找树的所有空链接到根节点的距离应该是相同的
插入操作
2-3查找树的插入操作与二叉查找树的插入操作有很大的区别,二叉查找树插入操作是先进行一次未命中的查找,然后再将节点插入对应的空连接上。
2-3查找树插入操作是将新节点插入到叶子节点上
- 插入到2-节点上,那么直接将新节点和原来节点组成3-节点
- 如果是插入到3-节点上,就会产生一个临时的4-节点 ,需要将4-节点分裂成3个2-节点,并将中间的2-节点移到上层节点中。如果上移操作产生临时4-节点则一直分裂上移,知道不存在临时4-节点
2-3查找树的查找和插入操作复杂度和插入顺序无关,在最坏情况下查找和插入操作访问的节点必然不超过logN个。
红黑二叉查找树
红黑树中使用红链接来实现3-节点。指向一个节点的链接颜色如果是红色,那么这个节点和上层节点表示的是一个3-节点,而黑色则是普通连接
- 红链接都是左链接
- 完美黑色平衡,即任意空链接到根节点的路径上的黑链接数量相同
数据结构
1 | public class RedBlackBST<Key extends Comparable<Key>, Value> { |
左旋转
上面提到红链接都是左链接,如果出现红链接为有链接的时候,就要进行左旋操作
1 | public Node rotateLeft(Node h) { |
右旋转
进行右旋转是为了转换两个连续的左红连接
1 | public Node rotateRight(Node h) { |
颜色转化
一个4-节点在红黑树中表现为一个节点的左右节点都是红色的,分裂4-节点除了需要将子节点的颜色由红变黑外,同时需要将父节点的颜色由黑变红,从2-3树的角度看就是将中间节点移到上层节点。
1 | void flipColors(Node h){ |
插入操作
先将一个节点按照二叉查找树的方法插入到正确位置,然后再进行如下的颜色转换操作
- 如果右子节点是红色的而左子节点是黑色的,进行左旋转
- 如果左子节点是红色的,左子节点的左子节点也是红色的,进行右旋转
- 如果左右子节点都是红色的,进行颜色转化
1 | public void put(Key key, Value val) { |
根节点一定为黑色,因为根节点没有上层节点,也就没有上层节点的左链接指向根节点。flipColors() 有可能会使得根节点的颜色变为红色,每当根节点由红色变成黑色时树的黑链接高度加 1
分析
一颗大小为 N 的红黑树的高度不会超过 2logN。最坏的情况下是它所对应的 2-3 树,构成最左边的路径节点全部都是 3- 节点而其余都是 2- 节点。
红黑树大多数的操作所需要的时间都是对数级别的。