基本操作及Java代码实现-红黑树-数据结构和算法
目录
内容
上面一篇介绍了红黑树的概念、特征和时间复杂度,这里我们进一步讲解红黑树的基础操作和Java代码实现。
数据结构基本操作添加、修改、删除、查询,红黑树做为一种特殊的二叉查找树,其查找和修改同二叉查找树;但是添加、删除和二叉查找树有很大区别。
道理很简单,添加或删除红黑树中的节点之后,红黑树就发生了变化,可能不满足红黑树的5条性质,也就不再是一颗红黑树了,而是一颗普通的树。而通过旋转,可以使这颗树重新成为红黑树。简单点说,旋转的目的是让树保持红黑树的特性。
所有Java代码基本参照HashMap TreeNode完成。
1、红黑树构建
1.1、红黑树的节点分析
红黑树作为一种数据结构,基本功能-存储数据;作为二叉树,有左右子树(节点);具有自己独特的特点,每个节点都有颜色;为了方便查找某个节点的父级节点,用一个指针指向它 的父节点;
- 红黑树节点Java代码
static final class RBNode<K, V> {
final K key; // 关键字
V value; // 数据
boolean red; // 是否是红色
private RBNode<K, V> parent; // 父节点指针
private RBNode<K, V> left; // 左子节点指针
private RBNode<K, V> right; // 右子节点指针
// 构造函数
public RBNode(K key, V value, boolean red, RBNode<K, V> parent, RBNode<K, V> left, RBNode<K, V> right) {
this.key = key;
this.value = value;
this.red = red;
this.parent = parent;
this.left = left;
this.right = right;
}
/**
* 以当前节点起始,查找根节点
*/
final RBNode<K,V> root() {
for (RBNode<K,V> r = this, p;;) {
if ((p = r.parent) == null)
return r;
r = p;
}
}
}
1.2、 红黑树成员变量
要查看红黑树,需要有一个切入点,就是红黑树的根节点;想要指定存储了几个元素,需要size变量。
1.3、红黑树的基本操作
- 左旋
- 右旋
- 插入
- 插入后平衡跳转
- 删除
- 删除后平衡跳转
- 判断是否为空
- 获取元素个数
- 打印
- 查找(根据节点key)
1.4、红黑树类代码
完整代码在最后仓库地址。
2.变色
因为上面我设计用布尔值存储节点的颜色信息,这个很容易实现,通过设置true,节点为红色;false,节点为黑色。
图示:
3、左旋
-
旋转过程图示:
-
步骤
- 对目标节点p向左旋转(逆时针)
- p节点右节点r的左节点rl 成为 p的右节点,如果rl不为空,rl的父节点变为p节点
- p的父节点pp变为r的父节点,如果pp为空,则说明原p为根节点,现在根节点root指向r
- 如果p为pp的左节点,则pp的左节点设置为r;否则pp的右节点设置为r。
- p的父节点变为r,r的左节点变为p
- 代码实现
// 左旋
static <K, V> RBNode<K, V> rotateLeft(RBNode<K, V> root, RBNode<K, V> p) {
RBNode<K, V> r, pp, rl;
if (p != null && (r = p.right) != null) {
if ((rl = p.right = r.left) != null)
rl.parent = p;
if ((pp = r.parent = p.parent) == null)
(root = r).red = false;
else if (pp.left == p)
pp.left = r;
else
pp.right = r;
r.left = p;
p.parent = r;
}
return root;
}
3、右旋
-
旋转过程图示:
-
步骤
- 对目标节点p向右旋转(顺时针)
- p节点左节点l的右节点lr 成为 p的左节点,如果lr不为空,lr的父节点变为p节点
- p的父节点pp变为l的父节点,如果pp为空,则说明原p为根节点,现在根节点root指向l
- 如果p为pp的左节点,则pp的左节点设置为l;否则pp的右节点设置为l。
- p的父节点变为pl,pl的左节点变为p
- 代码实现
// 右旋
static <K, V> RBNode<K, V> rotateRight(RBNode<K, V> root, RBNode<K, V> p) {
RBNode<K, V> l, pp, lr;
if (p != null && (l = p.left) != null) {
if ((lr = p.left = l.right) != null)
lr.parent = p;
if ((pp = l.parent = p.parent) == null)
(root = l).red = false;
else if (pp.left == p)
pp.left = l;
else pp.right = l;
l.right = p;
p.parent = l;
}
return root;
}
后记 :
欢迎交流,本人QQ:806797785
项目源代码地址:https://gitee.com/gaogzhen/algorithm.git