Java红黑树保姆级带你了解,让面试官哑口无言

一,介绍

首先,红黑树是一种自平衡的二叉搜索树,它通过颜色标记和旋转操作来维持树的平衡。红黑树将节点分为红色和黑色两种颜色,其中红色表示当前节点,而黑色表示子节点。

在下面图片中,我们可以使用以下代码来描述一个红黑树的基本结构:
在这里插入图片描述
表示了一个红黑树的根节点A,以及其左右子节点B和C。每个节点都可能拥有一个或两个子节点。对于每个节点,我们可以根据其颜色将其标记为红色或黑色。在Mermaid格式中,我们可以通过在节点标签中添加颜色后缀来表示节点的颜色。例如,红色节点可以表示为<红色>,而黑色节点可以表示为<黑色>。

为了更详细地描述红黑树的特性,我们可以在代码中添加一些额外的注释和说明。例如,我们可以使用箭头符号来指示节点的旋转方向,以及在注释中说明节点颜色的变化。以下是一个更详细的图片:
在这里插入图片描述

二,Java示例代码

以下是一个Java实现的红黑树的示例代码。代码中包含了详细的注释,以便更好地理解每个步骤的含义和作用。

// 定义红黑树节点的颜色
enum Color {
    
    
    RED,
    BLACK
}

// 红黑树节点类
class Node {
    
    
    int data;
    Color color;
    Node parent;
    Node left;
    Node right;

    // 构造函数
    public Node(int data) {
    
    
        this.data = data;
        this.color = Color.RED;
        this.parent = null;
        this.left = null;
        this.right = null;
    }
}

// 红黑树类
public class RedBlackTree {
    
    
    private Node root;
    private Node nil; // 哨兵节点

    // 构造函数
    public RedBlackTree() {
    
    
        nil = new Node(0);
        nil.color = Color.BLACK;
        root = nil;
    }

    // 左旋操作
    private void leftRotate(Node x) {
    
    
        Node y = x.right;
        x.right = y.left;

        if (y.left != nil) {
    
    
            y.left.parent = x;
        }

        y.parent = x.parent;

        if (x.parent == nil) {
    
    
            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(Node y) {
    
    
        Node x = y.left;
        y.left = x.right;

        if (x.right != nil) {
    
    
            x.right.parent = y;
        }

        x.parent = y.parent;

        if (y.parent == nil) {
    
    
            root = x;
        } else if (y == y.parent.left) {
    
    
            y.parent.left = x;
        } else {
    
    
            y.parent.right = x;
        }

        x.right = y;
        y.parent = x;
    }

    // 插入节点
    public void insert(int data) {
    
    
        Node node = new Node(data);
        Node y = nil;
        Node x = root;

        while (x != nil) {
    
    
            y = x;
            if (node.data < x.data) {
    
    
                x = x.left;
            } else {
    
    
                x = x.right;
            }
        }

        node.parent = y;

        if (y == nil) {
    
    
            root = node;
        } else if (node.data < y.data) {
    
    
            y.left = node;
        } else {
    
    
            y.right = node;
        }

        node.left = nil;
        node.right = nil;
        node.color = Color.RED;
        insertFixup(node);
    }

    // 插入修复操作
    private void insertFixup(Node node) {
    
    
        while (node.parent.color == Color.RED) {
    
    
            if (node.parent == node.parent.parent.left) {
    
    
                Node y = node.parent.parent.right;

                if (y.color == Color.RED) {
    
    
                    node.parent.color = Color.BLACK;
                    y.color = Color.BLACK;
                    node.parent.parent.color = Color.RED;
                    node = node.parent.parent;
                } else {
    
    
                    if (node == node.parent.right) {
    
    
                        node = node.parent;
                        leftRotate(node);
                    }

                    node.parent.color = Color.BLACK;
                    node.parent.parent.color = Color.RED;
                    rightRotate(node.parent.parent);
                }
            } else {
    
    
                Node y = node.parent.parent.left;

                if (y.color == Color.RED) {
    
    
                    node.parent.color = Color.BLACK;
                    y.color = Color.BLACK;
                    node.parent.parent.color = Color.RED;
                    node = node.parent.parent;
                } else {
    
    
                    if (node == node.parent.left) {
    
    
                        node = node.parent;
                        rightRotate(node);
                    }

                    node.parent.color = Color.BLACK;
                    node.parent.parent.color = Color.RED;
                    leftRotate(node.parent.parent);
                }
            }
        }

        root.color = Color.BLACK;
    }

    // 中序遍历红黑树
    private void inorderTraversal(Node node) {
    
    
        if (node != nil) {
    
    
            inorderTraversal(node.left);
            System.out.print(node.data + " ");
            inorderTraversal(node.right);
        }
    }

    // 打印红黑树
    public void printTree() {
    
    
        inorderTraversal(root);
        System.out.println();
    }

    // 测试红黑树
    public static void main(String[] args) {
    
    
        RedBlackTree tree = new RedBlackTree();
        tree.insert(30);
        tree.insert(20);
        tree.insert(40);
        tree.insert(10);
        tree.insert(25);
        tree.insert(35);
        tree.insert(50);

        tree.printTree();
    }
}

这是一个基本的红黑树实现,包含了节点的插入操作、左旋和右旋操作以及插入修复操作。你可以使用insert()方法插入节点,然后使用printTree()方法打印红黑树的中序遍历结果。在示例中,我们插入了一些节点并打印了红黑树的结果。

请注意,这只是一个简单的示例代码,实际应用中可能需要根据具体需求进行修改和扩展。

三技术细节

红黑树是一种自平衡的二叉搜索树,具有以下特点:

  1. 每个节点都有一个颜色,红色或黑色。
  2. 根节点是黑色的。
  3. 所有叶子节点(NIL节点)都是黑色的。
  4. 如果一个节点是红色的,则它的两个子节点都是黑色的。
  5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数量的黑色节点。

这些特性确保了红黑树的平衡性和高效性,使得其在插入、删除和查找操作上具有较好的性能。

以下是红黑树的一些关键操作的技术细节:

  1. 左旋操作:

    • 首先,将节点y的左子节点设为x的右子节点,并将x的父节点设为y的父节点。
    • 然后,更新x的右子节点的父节点为x。
    • 接着,将x的父节点设为y,并更新y的子节点(根据x在其父节点的位置)。
    • 最后,将y设为x的左子节点,将x设为y的父节点。
  2. 右旋操作:

    • 首先,将节点x的右子节点设为y的左子节点,并将y的父节点设为x的父节点。
    • 然后,更新y的左子节点的父节点为y。
    • 接着,将y的父节点设为x,并更新x的子节点(根据y在其父节点的位置)。
    • 最后,将x设为y的右子节点,将y设为x的父节点。
  3. 插入操作:

    • 首先,将节点插入到红黑树中的适当位置,类似于二叉搜索树的插入操作。
    • 然后,将插入节点的颜色设为红色。
    • 接着,通过插入修复操作来恢复红黑树的平衡性。
    • 插入修复操作包括以下情况的处理:
      • 当插入节点的父节点是红色,并且叔节点也是红色时,需要进行颜色调整。
      • 当插入节点的父节点是红色,并且叔节点是黑色时,需要进行旋转操作和颜色调整。
  4. 删除操作:

    • 首先,执行二叉搜索树的删除操作,将节点删除。
    • 然后,通过删除修复操作来恢复红黑树的平衡性。
    • 删除修复操作包括以下情况的处理:
      • 当删除节点是红色节点时,不需要进行修复操作。
      • 当删除节点是黑色节点时,需要对其兄弟节点进行不同情况的判断和处理。

这些是红黑树的一些关键技术细节,用于保持树的平衡性和性能。实际的红黑树实现可能还包括其他辅助函数和操作,以满足特定的需求和场景。

四小结

红黑树是一种自平衡的二叉搜索树,具有高效的插入、删除和查找操作。它的关键特点包括节点的颜色(红色或黑色)、根节点为黑色、叶子节点为黑色、红色节点的子节点为黑色、任意节点到其后代叶子节点的简单路径上包含相同数量的黑色节点。

红黑树的主要操作包括左旋和右旋操作,用于调整树的结构,以及插入和删除操作,用于维护树的平衡性。左旋操作将一个节点的右子节点旋转到该节点的位置,右旋操作将一个节点的左子节点旋转到该节点的位置。插入操作将新节点插入到适当的位置,并通过插入修复操作来恢复树的平衡性。删除操作删除指定节点,并通过删除修复操作来恢复树的平衡性。

红黑树的实现中,需要注意节点的颜色、父节点、左子节点和右子节点的管理,以及对树的结构进行调整和修复。红黑树的性质保证了树的平衡性,使得其在各种操作下都能保持较好的性能。

红黑树是一种重要的数据结构,被广泛应用于各种领域,例如编译器、数据库、操作系统等。它提供了一种高效的平衡二叉搜索树解决方案,可以在大规模数据集上快速进行插入、删除和查找操作。

猜你喜欢

转载自blog.csdn.net/qq_49841284/article/details/134866014