当前位置:首页 > C++ > 正文

深入理解C++红黑树(从零开始掌握C++红黑树实现方法)

在计算机科学中,红黑树是一种自平衡的二叉查找树,它在插入和删除操作后通过重新着色和旋转来保持树的平衡。这种数据结构被广泛应用于 C++ 标准库中的 std::mapstd::set 等容器。本教程将带你从零开始,用 C++红黑树实现一个完整的红黑树,并详细解释其核心原理。

什么是红黑树?

红黑树是一种满足以下五条性质的二叉搜索树:

  1. 每个节点要么是红色,要么是黑色。
  2. 根节点是黑色。
  3. 所有叶子节点(NIL 节点,通常用空指针表示)是黑色。
  4. 如果一个节点是红色,则它的两个子节点都是黑色。(即不能有两个连续的红色节点)
  5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

这些规则确保了树的高度始终保持在 O(log n) 级别,从而保证了查找、插入和删除操作的时间复杂度为 O(log n)

深入理解C++红黑树(从零开始掌握C++红黑树实现方法) C++红黑树实现 红黑树插入删除 C++数据结构教程 红黑树平衡算法 第1张

C++红黑树的基本结构

我们首先定义红黑树的节点结构。每个节点包含:键值、颜色、父节点指针、左右子节点指针。

enum Color { RED, BLACK };struct Node {    int key;    Color color;    Node* left;    Node* right;    Node* parent;    Node(int k) : key(k), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}};

红黑树的核心操作

红黑树的关键在于插入删除后的修复操作。我们重点讲解插入过程。

1. 插入新节点

首先像普通二叉搜索树一样插入节点,并将其颜色设为红色(避免破坏黑色高度)。然后调用修复函数 fixInsert 来恢复红黑树性质。

class RedBlackTree {private:    Node* root;    Node* NIL; // 代表空叶子节点    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 == nullptr)            root = y;        else if (x == x->parent->left)            x->parent->left = y;        else            x->parent->right = y;        y->left = x;        x->parent = y;    }    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 == nullptr)            root = x;        else if (y == y->parent->right)            y->parent->right = x;        else            y->parent->left = x;        x->right = y;        y->parent = x;    }    void fixInsert(Node* k) {        while (k != root && k->parent->color == RED) {            if (k->parent == k->parent->parent->right) {                Node* u = k->parent->parent->left; // uncle                if (u != NIL && u->color == RED) {                    u->color = BLACK;                    k->parent->color = BLACK;                    k->parent->parent->color = RED;                    k = k->parent->parent;                } else {                    if (k == k->parent->left) {                        k = k->parent;                        rightRotate(k);                    }                    k->parent->color = BLACK;                    k->parent->parent->color = RED;                    leftRotate(k->parent->parent);                }            } else {                Node* u = k->parent->parent->right; // uncle                if (u != NIL && u->color == RED) {                    u->color = BLACK;                    k->parent->color = BLACK;                    k->parent->parent->color = RED;                    k = k->parent->parent;                } else {                    if (k == k->parent->right) {                        k = k->parent;                        leftRotate(k);                    }                    k->parent->color = BLACK;                    k->parent->parent->color = RED;                    rightRotate(k->parent->parent);                }            }        }        root->color = BLACK;    }public:    RedBlackTree() {        NIL = new Node(0);        NIL->color = BLACK;        root = NIL;    }    void insert(int key) {        Node* node = new Node(key);        node->left = NIL;        node->right = NIL;        Node* y = nullptr;        Node* x = root;        while (x != NIL) {            y = x;            if (node->key < x->key)                x = x->left;            else                x = x->right;        }        node->parent = y;        if (y == nullptr)            root = node;        else if (node->key < y->key)            y->left = node;        else            y->right = node;        if (node->parent == nullptr) {            node->color = BLACK;            return;        }        if (node->parent->parent == nullptr)            return;        fixInsert(node);    }};

2. 删除操作(简要说明)

删除比插入更复杂,涉及双黑节点等情况。由于篇幅限制,这里不展开完整代码,但核心思想是:先按 BST 方式删除,若删除的是黑色节点,则需调用 fixDelete 进行颜色调整和旋转,以维持红黑树性质。这是 红黑树插入删除中最难的部分。

为什么学习红黑树?

掌握 C++数据结构教程中的红黑树,不仅能提升你对底层数据结构的理解,还能帮助你在面试中脱颖而出。更重要的是,理解 红黑树平衡算法有助于你设计高性能的程序。

总结

本教程从红黑树的基本性质出发,逐步构建了一个支持插入操作的 C++ 红黑树实现。虽然完整实现(包括删除)较为复杂,但只要理解了旋转和颜色修复的逻辑,就能掌握这一强大的 C++红黑树实现技巧。

建议读者动手编写代码,并配合调试工具观察树的结构变化,加深理解。红黑树虽难,但值得攻克!