Java red-black tree nanny-level guide you to understand, leaving the interviewer speechless

1. Introduction

First of all, the red-black tree is a self-balancing binary search tree that maintains the balance of the tree through color marking and rotation operations. Red-black trees divide nodes into two colors: red and black, where red represents the current node and black represents child nodes.

In the picture below, we can use the following code to describe the basic structure of a red-black tree:
Insert image description here
represents the root node A of a red-black tree, and its left and right child nodes B and C. Each node may have one or two child nodes. For each node, we can mark it as red or black depending on its color. In Mermaid format, we can represent the color of a node by adding a color suffix to the node label. For example, a red node can be represented as <red>, while a black node can be represented as <black>.

In order to describe the characteristics of red-black trees in more detail, we can add some additional comments and explanations to the code. For example, we can use arrow symbols to indicate the direction of a node's rotation, as well as illustrate node color changes in annotations. Here's a more detailed picture:
Insert image description here

2. Java sample code

The following is a sample code for a red-black tree implemented in Java. Detailed comments are included in the code to better understand the meaning and effect of each step.

// 定义红黑树节点的颜色
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();
    }
}

This is a basic red-black tree implementation, including node insertion operations, left-turn and right-turn operations, and insertion and repair operations. You can use the insert() method to insert nodes, and then use the printTree() method to print the in-order traversal results of the red-black tree. In the example, we inserted some nodes and printed the result of the red-black tree.

Please note that this is just a simple sample code and may need to be modified and extended according to specific needs in actual applications.

Three technical details

The red-black tree is a self-balancing binary search tree with the following characteristics:

  1. Each node has a color, red or black.
  2. The root node is black.
  3. All leaf nodes (NIL nodes) are black.
  4. If a node is red, both of its child nodes are black.
  5. For each node, the simple path from that node to all its descendant leaf nodes contains the same number of black nodes.

These characteristics ensure the balance and efficiency of the red-black tree, giving it better performance in insertion, deletion and search operations.

Here are the technical details of some key operations of red-black trees:

  1. Left-hand rotation operation:

    • First, set the left child of node y to the right child of x, and set the parent of x to the parent of y.
    • Then, update the parent node of the right child node of x to x.
    • Next, set the parent node of x to y, and update the child nodes of y (according to the position of x in its parent node).
    • Finally, set y as the left child of x and set x as the parent of y.
  2. Right rotation operation:

    • First, set the right child of node x to the left child of y, and set the parent of y to the parent of x.
    • Then, update the parent node of y's left child node to y.
    • Next, set the parent node of y to x, and update the child nodes of x (according to the position of y in its parent node).
    • Finally, set x as the right child of y and y as the parent of x.
  3. Insert operation:

    • First, insert the node into the appropriate position in the red-black tree, similar to the insertion operation of the binary search tree.
    • Then, set the color of the inserted node to red.
    • Then, the balance of the red-black tree is restored by inserting repair operations.
    • Insert repair operations include processing of the following situations:
      • When the parent node of the inserted node is red and the uncle node is also red, color adjustment is required.
      • When the parent node of the inserted node is red and the uncle node is black, rotation operations and color adjustments are required.
  4. Delete operation:

    • First, perform the deletion operation of the binary search tree and delete the node.
    • Then, restore the balance of the red-black tree by removing the repair operation.
    • Delete repair operations include handling the following situations:
      • When the deleted node is a red node, no repair operation is required.
      • When the deleted node is a black node, its sibling nodes need to be judged and processed in different situations.

These are some of the key technical details of red-black trees that are used to keep the tree balanced and performant. Actual red-black tree implementations may also include other helper functions and operations to meet specific needs and scenarios.

Four summary

A red-black tree is a self-balancing binary search tree with efficient insertion, deletion, and search operations. Its key features include the color of the node (red or black), the root node is black, the leaf nodes are black, the child nodes of the red node are black, and the simple path from any node to its descendant leaf node contains the same number of black nodes.

The main operations of the red-black tree include left-turn and right-turn operations, which are used to adjust the structure of the tree, and insertion and deletion operations, which are used to maintain the balance of the tree. The left rotation operation rotates the right child node of a node to the position of the node, and the right rotation operation rotates the left child node of a node to the position of the node. The insertion operation inserts the new node into the appropriate location, and the insertion repair operation restores the balance of the tree. The delete operation deletes the specified node, and the delete repair operation restores the balance of the tree.

In the implementation of the red-black tree, you need to pay attention to the color of the node, the management of the parent node, left child node and right child node, as well as adjusting and repairing the tree structure. The nature of the red-black tree ensures the balance of the tree, allowing it to maintain good performance under various operations.

Red-black tree is an important data structure that is widely used in various fields, such as compilers, databases, operating systems, etc. It provides an efficient balanced binary search tree solution for fast insertion, deletion, and lookup operations on large-scale data sets.

Guess you like

Origin blog.csdn.net/qq_49841284/article/details/134866014