1. 2-3树
性质:1.结点可以存放一个元素或者两个元素,所以,每个结点有2个或3个孩子
2. 2-3是一颗绝对平衡的树
图示:
红黑树与2-3树的等价性:
2.什么是红黑树
红黑树是一种自平衡二叉查找树,实在计算机科学中用到的一种数据结构,其用途是实现关联数组。
红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。它可以在O(log n)时间内做查找,插入和删除
3.红黑树的基本性质
1.每个结点或者是红色的,或者时黑色的
2.根节点时黑色的
3.每一个叶子结点(最后的空结点)是黑色的
4.如果一个结点时红色的,那么他的孩子结点都是黑色的
5.从任意一个结点到叶子结点,经过的黑色结点是一样的
4.红黑树的代码实现
1.构建树
private class Node {
// 结点内容
T val;
// 左右孩子
Node left;
Node right;
Boolean isRed; // 记录结点的颜色
public Node(T val) {
this.val = val;
this.isRed = true;
this.left = null;
this.right = null;
}
}
Node root;//根节点
int size; // 树中结点的个数
public RBTree() {
this.root = null;
this.size = 0;
}
2.获取树中结点的个数
// 获取树中结点的个数
public int getSize() {
return this.size;
}
3.判断是否为空树
// 判断是否为空树
public boolean isEmpty() {
return this.root == null;
}
4.辅助方法:获取结点的颜色
// 辅助的方法: 获取结点的颜色
public boolean getColor(Node node) {
if (node == null) {
return false;
}
return node.isRed;
}
5.向树中添加结点
// 在以node为根的二分搜索树中添加val
private Node add(Node node, T val) {
// 1、递归终止的条件
if (node == null) {
this.size++;
return new Node(val);
}
// 2、递归操作
if (node.val.compareTo(val) > 0) {
node.left = add(node.left, val);
} else {
node.right = add(node.right, val);
}
// 以node结点为根的树不平衡,就要调整
Node resultNode = node;
// 左旋转
if (!getColor(resultNode.left) && getColor(resultNode.right)) {
resultNode = leftRotate(resultNode);
}
// 右旋转
if (getColor(resultNode.left) && getColor(resultNode.left.left)) {
resultNode = rightRotate(resultNode);
}
//颜色反转
if (getColor(resultNode.left) && getColor(resultNode.right)) {
flipColor(resultNode);
}
return resultNode;
}
6.查询val是否存在于树中
public Node find(T val) {
return find(root, val);
}
private Node find(Node node, T val) {
// 1、递归终止条件
if (node == null) {
return null;
}
// 2、 递归操作
if (node.val.compareTo(val) == 0) {
return node;
} else if (node.val.compareTo(val) < 0) {
return find(node.right, val);
} else {
return find(node.left, val);
}
}
7.层序遍历,并获取各结点的颜色
// 层序遍历,并获取个结点的颜色
public void levelTraverse() {
LinkedList<Node> queue = new LinkedList<>();
if (this.root == null) {
return;
}
queue.add(this.root);
while (!queue.isEmpty()) {
Node node = queue.poll();
System.out.println(node.val + "<---->" + (getColor(node)?"RED":"BLACK"));
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
}
8.方法补充(左旋转,右旋转,颜色反转)
/**
* 右旋转
*/
private Node rightRotate(Node node) {
Node x = node.left;
// 1、保存x的右子树
Node t2 = x.right;
// 2、将node作为x的右子树
x.right = node;
// 3、将t3作为y的左子树
node.left = t2;
// 更新颜色
x.isRed = node.isRed;
node.isRed = true;
return x;
}
/**
* 左旋转
*/
private Node leftRotate(Node node) {
Node x = node.right;
// 1、保存x的左孩子
Node t2 = x.left;
// 2、将node作为x的左树
x.left = node;
// 3、将t2作为node的右树
node.right = t2;
// 更新颜色
x.isRed = node.isRed;
node.isRed = true;
return x;
}
// 颜色反转
private void flipColor(Node node) {
node.isRed = true;
node.left.isRed = false;
node.right.isRed = false;
}