红黑树的一些理解

红黑树是一种自平衡的二叉查找树,它在每个节点上增加了一个额外的属性表示节点的颜色,可以是红色或黑色。通过满足一定的性质,红黑树确保了在进行插入、删除等操作时,树的高度保持在对数级别,从而保证了操作的时间复杂度为 O(log n)。

红黑树满足以下性质:

  1. 每个节点是红色或黑色。
  2. 根节点是黑色。
  3. 每个叶子节点(NIL节点,空节点)是黑色的。
  4. 如果一个节点是红色的,则它的两个子节点都是黑色的(不能有两个相连的红色节点)。
  5. 从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点(黑色节点数量相同)。

这里是一个简单的红黑树的 Java 实现,包含插入操作:

java 复制代码
class RedBlackTreeNode {
    int data;
    RedBlackTreeNode parent;
    RedBlackTreeNode left;
    RedBlackTreeNode right;
    int color;

    public RedBlackTreeNode(int data) {
        this.data = data;
        color = 1; // 新插入的节点默认为红色
        parent = left = right = null;
    }
}

public class RedBlackTree {
    private RedBlackTreeNode root;

    // 左旋
    private void leftRotate(RedBlackTreeNode x) {
        RedBlackTreeNode y = x.right;
        x.right = y.left;
        if (y.left != null)
            y.left.parent = x;
        y.parent = x.parent;
        if (x.parent == null)
            root = y;
        else if (x == x.parent.left)
            x.parent.left = y;
        else
            x.parent.right = y;
        y.left = x;
        x.parent = y;
    }

    // 右旋
    private void rightRotate(RedBlackTreeNode y) {
        RedBlackTreeNode x = y.left;
        y.left = x.right;
        if (x.right != null)
            x.right.parent = y;
        x.parent = y.parent;
        if (y.parent == null)
            root = x;
        else if (y == y.parent.right)
            y.parent.right = x;
        else
            y.parent.left = x;
        x.right = y;
        y.parent = x;
    }

    // 插入节点
    public void insert(int data) {
        RedBlackTreeNode newNode = new RedBlackTreeNode(data);
        RedBlackTreeNode parent = null;
        RedBlackTreeNode current = root;
        while (current != null) {
            parent = current;
            if (newNode.data < current.data)
                current = current.left;
            else
                current = current.right;
        }
        newNode.parent = parent;
        if (parent == null)
            root = newNode;
        else if (newNode.data < parent.data)
            parent.left = newNode;
        else
            parent.right = newNode;
        newNode.color = 1; // 新插入的节点默认为红色
        fixInsert(newNode);
    }

    // 插入后修复红黑树性质
    private void fixInsert(RedBlackTreeNode k) {
        RedBlackTreeNode u;
        while (k.parent.color == 1) {
            if (k.parent == k.parent.parent.right) {
                u = k.parent.parent.left;
                if (u.color == 1) {
                    u.color = 0;
                    k.parent.color = 0;
                    k.parent.parent.color = 1;
                    k = k.parent.parent;
                } else {
                    if (k == k.parent.left) {
                        k = k.parent;
                        rightRotate(k);
                    }
                    k.parent.color = 0;
                    k.parent.parent.color = 1;
                    leftRotate(k.parent.parent);
                }
            } else {
                u = k.parent.parent.right;

                if (u.color == 1) {
                    u.color = 0;
                    k.parent.color = 0;
                    k.parent.parent.color = 1;
                    k = k.parent.parent;
                } else {
                    if (k == k.parent.right) {
                        k = k.parent;
                        leftRotate(k);
                    }
                    k.parent.color = 0;
                    k.parent.parent.color = 1;
                    rightRotate(k.parent.parent);
                }
            }
            if (k == root) {
                break;
            }
        }
        root.color = 0;
    }

    // 中序遍历
    private void inorder(RedBlackTreeNode root) {
        if (root == null)
            return;
        inorder(root.left);
        System.out.print(root.data + " ");
        inorder(root.right);
    }

    public void inorder() {
        inorder(root);
    }

    public static void main(String[] args) {
        RedBlackTree tree = new RedBlackTree();
        tree.insert(10);
        tree.insert(20);
        tree.insert(30);
        tree.insert(40);
        tree.insert(50);
        tree.insert(60);
        tree.insert(70);

        System.out.println("红黑树中序遍历:");
        tree.inorder();
    }
}

这个实现中,左旋和右旋操作用于保持红黑树的性质。在插入操作中,先将新插入的节点标记为红色,然后通过 fixInsert() 方法来修复可能违反红黑树性质的地方。

让我们逐个讲解代码中的每个方法:

  1. RedBlackTreeNode 类:

    • 定义了红黑树节点的结构。
    • 每个节点包含 data(节点的值)、parent(父节点的引用)、left(左子节点的引用)、right(右子节点的引用)、color(节点的颜色,0 表示黑色,1 表示红色)。
  2. RedBlackTree 类:

    • root:红黑树的根节点。
  3. leftRotate(RedBlackTreeNode x) 方法:

    • 实现了左旋操作。
    • 参数 x 是要进行左旋的节点。
    • x 的右子节点 y 上移为 x 的父节点,x 成为 y 的左子节点。
    • 旋转后要更新节点的父节点引用。
  4. rightRotate(RedBlackTreeNode y) 方法:

    • 实现了右旋操作。
    • 参数 y 是要进行右旋的节点。
    • y 的左子节点 x 上移为 y 的父节点,y 成为 x 的右子节点。
    • 旋转后要更新节点的父节点引用。
  5. insert(int data) 方法:

    • 插入新节点到红黑树中。
    • 首先创建一个新节点,并按照二叉查找树的规则找到其应该插入的位置。
    • 将新节点插入,并将其颜色标记为红色。
    • 调用 fixInsert() 方法修正红黑树的性质。
  6. fixInsert(RedBlackTreeNode k) 方法:

    • 修复插入节点后可能违反红黑树性质的问题。
    • 参数 k 是刚刚插入的节点。
    • 通过对 k 的父节点、叔节点和祖父节点的颜色进行判断和旋转操作来保持红黑树的性质。
  7. inorder(RedBlackTreeNode root) 方法:

    • 中序遍历红黑树。
    • 递归地从左子树开始遍历,然后访问当前节点,最后递归地遍历右子树。
  8. inorder() 方法:

    • 对外提供的中序遍历方法的入口点。
  9. main(String[] args) 方法:

    • 测试主方法,创建一个红黑树对象,并插入一些节点,然后进行中序遍历以验证红黑树的正确性。

这些方法共同构成了一个简单的红黑树的实现,通过这些方法可以实现对红黑树的插入操作,并保持其性质。

红黑树通过保持以下两个性质来维持平衡:

  1. 黑色平衡性(Black-Height Balance):确保从根到叶子的每条路径上的黑色节点数目相同。换句话说,红黑树保证了所有路径上的黑色节点数目相等,这样就能够保证树的高度不会过高。

  2. 红色性质(Red Property):保证没有两个相邻的红色节点,也就是说,红色节点不能出现相连的情况。

这两个性质的作用如下:

  • 黑色平衡性 确保了红黑树的高度不会过高,使得其插入、删除等操作的时间复杂度保持在 O(log n) 级别。
  • 红色性质 则是为了防止出现连续的红色节点,这样可以避免了路径上出现两个相邻的红色节点,保证了在插入、删除等操作后的平衡性。

综合这两个性质,红黑树能够保持平衡,并且在动态插入、删除节点时,通过旋转和重新着色等操作来维护这些性质,从而保持树的平衡性。

相关推荐
Estar.Lee4 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
LNTON羚通4 小时前
摄像机视频分析软件下载LiteAIServer视频智能分析平台玩手机打电话检测算法技术的实现
算法·目标检测·音视频·监控·视频监控
2401_857610036 小时前
SpringBoot社团管理:安全与维护
spring boot·后端·安全
哭泣的眼泪4086 小时前
解析粗糙度仪在工业制造及材料科学和建筑工程领域的重要性
python·算法·django·virtualenv·pygame
凌冰_6 小时前
IDEA2023 SpringBoot整合MyBatis(三)
spring boot·后端·mybatis
码农飞飞6 小时前
深入理解Rust的模式匹配
开发语言·后端·rust·模式匹配·解构·结构体和枚举
一个小坑货6 小时前
Rust 的简介
开发语言·后端·rust
Microsoft Word6 小时前
c++基础语法
开发语言·c++·算法
天才在此7 小时前
汽车加油行驶问题-动态规划算法(已在洛谷AC)
算法·动态规划
monkey_meng7 小时前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust