📜  红黑树|套装2(插入)(1)

📅  最后修改于: 2023-12-03 15:41:13.997000             🧑  作者: Mango

红黑树|套装2(插入)

红黑树是一种自平衡二叉搜索树,相对于其他的平衡二叉树,红黑树在插入、删除节点等操作时,既能够保证平衡性,又能够减少旋转的次数,使得操作效率更高。本文介绍的是红黑树的插入操作。

1. 插入操作的基本思路

在插入节点时,先把节点作为一颗红色节点插入到二叉搜索树中,然后进行以下的调整:

  • 如果父节点是黑色的,那么插入的节点是红色,不会影响红黑树的性质,直接返回;
  • 如果父节点是红色的,那么需要进行调整,调整的方法分为两种情况:
    • 父节点的兄弟节点是红色的,这种情况下需要对父节点和兄弟节点进行着色,并进行旋转操作;
    • 父节点的兄弟节点是黑色的,这种情况下需要进行旋转操作,并修改节点的颜色。

其中,旋转操作分为左旋和右旋两种,可以通过交换节点的左右子节点顺序来实现。

2. 插入操作的代码实现

在实现插入操作时,需要考虑以下几个方面:

  • 如何进行节点的旋转操作,以保证平衡性?
  • 如何判断节点的兄弟节点的颜色?
  • 如何进行节点的着色操作?

以下是一段C++代码,实现了红黑树的插入操作:

#include<iostream>
using namespace std;

enum Color {RED, BLACK};

struct Node{
    int val;
    Color color;
    Node* left;
    Node* right;
    Node* parent;

    Node(int val){
        this->val = val;
        this->color = RED;
        this->left = NULL;
        this->right = NULL;
        this->parent = NULL;
    }
};

class RedBlackTree{
private:
    Node* root;

public:
    RedBlackTree(){
        root = NULL;
    }

    void insert(int val){
        Node* node = new Node(val);
        node->left = NULL;
        node->right = NULL;
        node->color = RED;
        node->parent = NULL;

        Node* curr = root;
        Node* parent = NULL;

        while(curr != NULL){
            parent = curr;

            if(val < curr->val){
                curr = curr->left;
            }else{
                curr = curr->right;
            }
        }

        node->parent = parent;

        if(parent == NULL){
            root = node;
        }else if(val < parent->val){
            parent->left = node;
        }else{
            parent->right = node;
        }

        fixViolation(node);
    }

    void fixViolation(Node* node){
        Node* parent = NULL;
        Node* grandparent = NULL;

        while(node != root && node->color == RED && node->parent->color == RED){
            parent = node->parent;
            grandparent = parent->parent;

            if(parent == grandparent->left){
                Node* uncle = grandparent->right;

                if(uncle != NULL && uncle->color == RED){
                    grandparent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandparent;
                }else{
                    if(node == parent->right){
                        rotateLeft(parent);
                        node = parent;
                        parent = node->parent;
                    }

                    rotateRight(grandparent);
                    swap(parent->color, grandparent->color);
                    node = parent;
                }
            }else{
                Node* uncle = grandparent->left;

                if(uncle != NULL && uncle->color == RED){
                    grandparent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandparent;
                }else{
                    if(node == parent->left){
                        rotateRight(parent);
                        node = parent;
                        parent = node->parent;
                    }

                    rotateLeft(grandparent);
                    swap(parent->color, grandparent->color);
                    node = parent;
                }
            }
        }

        root->color = BLACK;
    }

    void rotateLeft(Node* node){
        Node* rightChild = node->right;
        node->right = rightChild->left;

        if(node->right != NULL){
            node->right->parent = node;
        }

        rightChild->parent = node->parent;

        if(node->parent == NULL){
            root = rightChild;
        }else if(node == node->parent->left){
            node->parent->left = rightChild;
        }else{
            node->parent->right = rightChild;
        }

        rightChild->left = node;
        node->parent = rightChild;
    }

    void rotateRight(Node* node){
        Node* leftChild = node->left;
        node->left = leftChild->right;

        if(node->left != NULL){
            node->left->parent = node;
        }

        leftChild->parent = node->parent;

        if(node->parent == NULL){
            root = leftChild;
        }else if(node == node->parent->left){
            node->parent->left = leftChild;
        }else{
            node->parent->right = leftChild;
        }

        leftChild->right = node;
        node->parent = leftChild;
    }

    void printTree(Node* node, int indent = 0){
        if(node == NULL){
            return;
        }

        if(node->right != NULL){
            printTree(node->right, indent + 4);
        }

        if(indent > 0){
            cout << setw(indent) << " ";
        }

        cout << node->val;

        if(node->color == RED){
            cout << " (R)";
        }else{
            cout << " (B)";
        }

        cout << endl;

        if(node->left != NULL){
            printTree(node->left, indent + 4);
        }
    }

    void inorderTraversal(Node* node){
        if(node == NULL){
            return;
        }

        inorderTraversal(node->left);
        cout << node->val << " ";
        inorderTraversal(node->right);
    }
};

int main(){
    RedBlackTree rbTree;
    rbTree.insert(7);
    rbTree.insert(6);
    rbTree.insert(5);
    rbTree.insert(4);
    rbTree.insert(3);
    rbTree.insert(2);
    rbTree.insert(1);

    cout << "Inorder traversal of the tree: " << endl;
    rbTree.inorderTraversal(rbTree.getRoot());
    cout << endl;

    cout << "Red Black Tree:" << endl;
    rbTree.printTree(rbTree.getRoot(), 0);

    return 0;
}
3. 测试样例

插入的元素为7, 6, 5, 4, 3, 2, 1,输出的结果如下:

Inorder traversal of the tree:
1 2 3 4 5 6 7 
Red Black Tree:
    7 (B)
        6 (B)
            5 (R)
                4 (B)
                3 (R)
            2 (B)
        1 (R)