2025-11-27 C++紅黑樹(shù)封裝實(shí)戰(zhàn):實(shí)現(xiàn)簡(jiǎn)易map與set容器

# C++紅黑樹(shù)封裝實(shí)戰(zhàn):實(shí)現(xiàn)簡(jiǎn)易map與set容器

紅黑樹(shù)作為一種自平衡的二叉搜索樹(shù),是C++標(biāo)準(zhǔn)庫(kù)中map和set容器的底層實(shí)現(xiàn)。本文將詳細(xì)介紹如何使用紅黑樹(shù)封裝實(shí)現(xiàn)簡(jiǎn)易的mymap和myset容器。

## 紅黑樹(shù)基礎(chǔ)概念

紅黑樹(shù)通過(guò)特定的著色規(guī)則和旋轉(zhuǎn)操作維持平衡,確保最壞情況下的操作時(shí)間復(fù)雜度為O(log n)。紅黑樹(shù)滿(mǎn)足以下性質(zhì):

1. 每個(gè)節(jié)點(diǎn)要么是紅色,要么是黑色

2. 根節(jié)點(diǎn)是黑色

3. 所有葉子節(jié)點(diǎn)(NIL節(jié)點(diǎn))都是黑色

4. 紅色節(jié)點(diǎn)的子節(jié)點(diǎn)必須是黑色

5. 從任一節(jié)點(diǎn)到其每個(gè)葉子節(jié)點(diǎn)的路徑包含相同數(shù)量的黑色節(jié)點(diǎn)

## 紅黑樹(shù)節(jié)點(diǎn)設(shè)計(jì)

首先定義紅黑樹(shù)節(jié)點(diǎn)的基本結(jié)構(gòu):

```cpp

enum Color { RED, BLACK };

template<typename T>

struct RBTreeNode {

? ? T data;

? ? Color color;

? ? RBTreeNode* left;

? ? RBTreeNode* right;

? ? RBTreeNode* parent;


? ? RBTreeNode(const T& val, Color c = RED)

? ? ? ? : data(val), color(c), left(nullptr), right(nullptr), parent(nullptr) {}

};

```

## 紅黑樹(shù)核心實(shí)現(xiàn)

### 基本框架

```cpp

template<typename K, typename V, typename KeyOfValue>

class RBTree {<"8B.2597.HK">

public:

? ? using Node = RBTreeNode<V>;


? ? RBTree() : root(nullptr), size_(0) {}

? ? ~RBTree() { clear(); }


? ? // 基本接口

? ? bool insert(const V& value);

? ? bool erase(const K& key);

? ? Node* find(const K& key) const;

? ? void clear();

? ? size_t size() const { return size_; }

? ? bool empty() const { return size_ == 0; }


private:

? ? Node* root;

? ? size_t size_;

? ? KeyOfValue keyOfValue;


? ? // 內(nèi)部輔助函數(shù)

? ? void leftRotate(Node* x);

? ? void rightRotate(Node* y);

? ? void insertFixup(Node* z);

? ? void eraseFixup(Node* x);

? ? Node* minimum(Node* node) const;

? ? Node* maximum(Node* node) const;

? ? void transplant(Node* u, Node* v);

? ? void destroy(Node* node);

};

```

### 旋轉(zhuǎn)操作

旋轉(zhuǎn)是維持紅黑樹(shù)平衡的關(guān)鍵操作:

```cpp

template<typename K, typename V, typename KeyOfValue>

void RBTree<K, V, KeyOfValue>::leftRotate(Node* x) {

? ? Node* y = x->right;

? ? x->right = y->left;


? ? if (y->left != nullptr) {

? ? ? ? y->left->parent = x;

? ? }


? ? y->parent = x->parent;


? ? if (x->parent == nullptr) {

? ? ? ? root = y<"2J.2597.HK">;

? ? } else if (x == x->parent->left) {

? ? ? ? x->parent->left = y;

? ? } else {

? ? ? ? x->parent->right = y;

? ? }


? ? y->left = x;

? ? x->parent = y;

}

template<typename K, typename V, typename KeyOfValue>

void RBTree<K, V, KeyOfValue>::rightRotate(Node* y) {

? ? Node* x = y->left;

? ? y->left = x->right;


? ? if (x->right != nullptr) {

? ? ? ? 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;

}

```

### 插入操作

```cpp

template<typename K, typename V, typename KeyOfValue>

bool RBTree<K, V, KeyOfValue>::insert(const V& value) {

? ? Node* z = new Node(value);

? ? Node* y = nullptr;

? ? Node* x = root;


? ? // 標(biāo)準(zhǔn)BST插入

? ? while (x != nullptr) {

? ? ? ? y = x;

? ? ? ? if (keyOfValue(z->data) < keyOfValue(x->data)) {

? ? ? ? ? ? x = x->left;

? ? ? ? } else if (keyOfValue(z->data) > keyOfValue(x->data)) {

? ? ? ? ? ? x = x->right;

? ? ? ? } else {

? ? ? ? ? ? // 鍵值已存在

? ? ? ? ? ? delete z;

? ? ? ? ? ? return false;

? ? ? ? }

? ? }


? ? z->parent = y;

? ? if (y == nullptr) {

? ? ? ? root = z;

? ? } else if (keyOfValue(z->data) < keyOfValue(y->data)) {

? ? ? ? y->left = z<"5L.2597.HK">;

? ? } else {

? ? ? ? y->right = z;

? ? }


? ? // 插入修復(fù)

? ? insertFixup(z);

? ? size_++;

? ? return true;

}

template<typename K, typename V, typename KeyOfValue>

void RBTree<K, V, KeyOfValue>::insertFixup(Node* z) {

? ? while (z->parent != nullptr && z->parent->color == RED) {

? ? ? ? if (z->parent == z->parent->parent->left) {

? ? ? ? ? ? Node* y = z->parent->parent->right;

? ? ? ? ? ? if (y != nullptr && y->color == RED) {

? ? ? ? ? ? ? ? // 情況1:叔節(jié)點(diǎn)為紅色

? ? ? ? ? ? ? ? z->parent->color = BLACK;

? ? ? ? ? ? ? ? y->color = BLACK;

? ? ? ? ? ? ? ? z->parent->parent->color = RED;

? ? ? ? ? ? ? ? z = z->parent->parent;

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? if (z == z->parent->right) {

? ? ? ? ? ? ? ? ? ? // 情況2:z是右孩子

? ? ? ? ? ? ? ? ? ? z = z->parent;

? ? ? ? ? ? ? ? ? ? leftRotate(z);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? // 情況3:z是左孩子

? ? ? ? ? ? ? ? z->parent->color = BLACK;

? ? ? ? ? ? ? ? z->parent->parent->color = RED;

? ? ? ? ? ? ? ? rightRotate(z->parent->parent);

? ? ? ? ? ? }

? ? ? ? } else {

? ? ? ? ? ? // 對(duì)稱(chēng)情況

? ? ? ? ? ? Node* y = z->parent->parent->left;

? ? ? ? ? ? if (y != nullptr && y->color == RED) {

? ? ? ? ? ? ? ? z->parent->color = BLACK;

? ? ? ? ? ? ? ? y->color = BLACK;

? ? ? ? ? ? ? ? z->parent->parent->color = RED;

? ? ? ? ? ? ? ? z = z->parent->parent;

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? if (z == z->parent->left) {

? ? ? ? ? ? ? ? ? ? z = z->parent;

? ? ? ? ? ? ? ? ? ? rightRotate(z);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? z->parent->color = BLACK;

? ? ? ? ? ? ? ? z->parent->parent->color = RED;

? ? ? ? ? ? ? ? leftRotate(z->parent->parent);

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? root->color = BLACK;

}

```

## 迭代器實(shí)現(xiàn)

為容器提供迭代器支持:

```cpp

template<typename T>

class RBTIterator {

public:

? ? using Node = RBTreeNode<T>;


? ? RBTIterator(Node* node = nullptr) : current(node) {}


? ? T& operator*() const { return current->data; }

? ? T* operator->() const { return &(current->data); }


? ? RBTIterator& operator++() {

? ? ? ? if (current->right != nullptr) {

? ? ? ? ? ? current = current->right;

? ? ? ? ? ? while (current->left != nullptr) {

? ? ? ? ? ? ? ? current = current->left;

? ? ? ? ? ? }

? ? ? ? } else {

? ? ? ? ? ? Node* p = current->parent;

? ? ? ? ? ? while (p != nullptr && current == p->right) {

? ? ? ? ? ? ? ? current = p;

? ? ? ? ? ? ? ? p = p->parent;

? ? ? ? ? ? }

? ? ? ? ? ? current = p;

? ? ? ? }

? ? ? ? return *this;

? ? }


? ? bool operator==(const RBTIterator& other) const {

? ? ? ? return current == other.current;

? ? }


? ? bool operator!=(const RBTIterator& other) const {

? ? ? ? return !(*this == other)<"9S.2597.HK">;

? ? }


private:

? ? Node* current;

};

```

## myset容器實(shí)現(xiàn)

基于紅黑樹(shù)封裝set容器:

```cpp

template<typename K>

class myset {

private:

? ? struct SetKeyOfValue {

? ? ? ? const K& operator()(const K& key) const { return key; }

? ? };


? ? using TreeType = RBTree<K, K, SetKeyOfValue>;


public:

? ? using iterator = RBTIterator<K>;

? ? using const_iterator = RBTIterator<const K>;


? ? myset() : tree() {}


? ? // 容量相關(guān)

? ? bool empty() const { return tree.empty(); }

? ? size_t size() const { return tree.size(); }


? ? // 修改操作

? ? bool insert(const K& key) { return tree.insert(key); }

? ? bool erase(const K& key) { return tree.erase(key); }

? ? void clear() { tree.clear(); }


? ? // 查找操作

? ? iterator find(const K& key) {

? ? ? ? return iterator(tree.find(key));

? ? }


? ? const_iterator find(const K& key) const {

? ? ? ? return const_iterator(tree.find(key));

? ? }


? ? // 迭代器

? ? iterator begin() {

? ? ? ? return iterator(tree.minimum(tree.getRoot()));

? ? }


? ? iterator end() { return iterator(nullptr); }


? ? const_iterator begin() const {

? ? ? ? return const_iterator(tree.minimum(tree.getRoot()));

? ? }


? ? const_iterator end() const { return const_iterator(nullptr); }


private:

? ? TreeType tree;

};

```

## mymap容器實(shí)現(xiàn)

基于紅黑樹(shù)封裝map容器:

```cpp

template<typename K, typename V>

class mymap {

private:

? ? using ValueType = std::pair<const K, V>;


? ? struct MapKeyOfValue {

? ? ? ? const K& operator()(const ValueType& val) const { return val.first; }

? ? };


? ? using TreeType = RBTree<K, ValueType, MapKeyOfValue>;


public:

? ? using iterator = RBTIterator<ValueType>;

? ? using const_iterator = RBTIterator<const ValueType>;


? ? mymap() : tree() {}


? ? // 元素訪(fǎng)問(wèn)

? ? V& operator[](const K& key) {

? ? ? ? auto it = find(key);

? ? ? ? if (it == end()) {

? ? ? ? ? ? auto result = insert(std::make_pair(key, V()));

? ? ? ? ? ? it = result.first;

? ? ? ? }

? ? ? ? return it->second;

? ? }


? ? // 修改操作

? ? std::pair<iterator, bool> insert(const ValueType& value) {

? ? ? ? bool inserted = tree.insert(value);

? ? ? ? return std::make_pair(find(value.first), inserted);

? ? }


? ? bool erase(const K& key) { return tree.erase(key); }

? ? void clear() { tree.clear(); }


? ? // 查找操作

? ? iterator find(const K& key) {

? ? ? ? return iterator(tree.find(key));

? ? }


? ? const_iterator find(const K& key) const {

? ? ? ? return const_iterator(tree.find(key));

? ? }


? ? // 容量相關(guān)

? ? bool empty() const { return tree.empty(); }

? ? size_t size() const { return tree.size(); }


? ? // 迭代器

? ? iterator begin()<"3F.2597.HK"> {

? ? ? ? return iterator(tree.minimum(tree.getRoot()));

? ? }


? ? iterator end() { return iterator(nullptr); }


? ? const_iterator begin() const {

? ? ? ? return const_iterator(tree.minimum(tree.getRoot()));

? ? }


? ? const_iterator end() const { return const_iterator(nullptr); }


private:

? ? TreeType tree;

};

```

## 刪除操作實(shí)現(xiàn)

紅黑樹(shù)的刪除操作相對(duì)復(fù)雜,需要仔細(xì)處理各種情況:

```cpp

template<typename K, typename V, typename KeyOfValue>

bool RBTree<K, V, KeyOfValue>::erase(const K& key) {

? ? Node* z = find(key);

? ? if (z == nullptr) return false;


? ? Node* y = z;

? ? Node* x = nullptr;

? ? Color y_original_color = y->color;


? ? if (z->left == nullptr) {

? ? ? ? x = z->right;

? ? ? ? transplant(z, z->right);

? ? } else if (z->right == nullptr) {

? ? ? ? x = z->left;

? ? ? ? transplant(z, z->left);

? ? } else {

? ? ? ? y = minimum(z->right);

? ? ? ? y_original_color = y->color;

? ? ? ? x = y->right;


? ? ? ? if (y->parent == z) {

? ? ? ? ? ? if (x != nullptr) x->parent = y;

? ? ? ? } else {

? ? ? ? ? ? transplant(y, y->right);

? ? ? ? ? ? y->right = z->right;

? ? ? ? ? ? if (y->right != nullptr) y->right->parent = y;

? ? ? ? }


? ? ? ? transplant(z, y);

? ? ? ? y->left = z->left;

? ? ? ? y->left->parent = y;

? ? ? ? y->color = z->color;

? ? }


? ? if (y_original_color == BLACK && x != nullptr) {

? ? ? ? eraseFixup(x);

? ? }


? ? delete z;

? ? size_--;

? ? return true;

}

```

## 使用示例

測(cè)試實(shí)現(xiàn)的mymap和myset容器:

```cpp

#include <iostream>

#include <string>

void test_mymap() {

? ? mymap<std::string, int> age_map;


? ? // 插入元素

? ? age_map.insert({"Alice", 25});

? ? age_map.insert({"Bob", 30});

? ? age_map["Charlie"] = 35;


? ? // 訪(fǎng)問(wèn)元素

? ? std::cout << "Alice's age: " << age_map["Alice"] << std::endl;


? ? // 遍歷

? ? for (const auto& pair : age_map) {

? ? ? ? std::cout << pair.first << ": " << pair.second << std::endl;

? ? }


? ? // 查找

? ? auto it = age_map.find("Bob");

? ? if (it != age_map.end()) {

? ? ? ? std::cout << "Found Bob, age: " << it->second << std::endl;

? ? }

}

void test_myset() {

? ? myset<int> number_set;


? ? number_set.insert(10);

? ? number_set.insert(20);

? ? number_set.insert(30);

? ? number_set.insert(20); // 重復(fù)元素,不會(huì)插入


? ? for (const auto& num : number_set) {

? ? ? ? std::cout << num << " ";

? ? }

? ? std::cout << std::endl;


? ? std::cout << "Set size: " << number_set.size() << std::endl;

}

int main() {

? ? test_mymap();

? ? test_myset();

? ? return 0;

}

```

## 性能分析與優(yōu)化

### 時(shí)間復(fù)雜度分析

- 插入操作:O(log n)

- 刪除操作:O(log n)

- 查找操作:O(log n)

- 遍歷操作:O(n)

### 內(nèi)存管理優(yōu)化

```cpp

// 添加內(nèi)存池支持

template<typename T>

class RBTreeMemoryPool {

private:

? ? std::vector<RBTreeNode<T>*> nodes;

? ? size_t current_index;


public:

? ? RBTreeNode<T>* allocate(const T& value, Color color) {

? ? ? ? if (current_index >= nodes.size())<"6P.2597.HK"> {

? ? ? ? ? ? nodes.push_back(new RBTreeNode<T>(value, color));

? ? ? ? } else {

? ? ? ? ? ? nodes[current_index]->data = value;

? ? ? ? ? ? nodes[current_index]->color = color;

? ? ? ? ? ? nodes[current_index]->left = nullptr;

? ? ? ? ? ? nodes[current_index]->right = nullptr;

? ? ? ? ? ? nodes[current_index]->parent = nullptr;

? ? ? ? }

? ? ? ? return nodes[current_index++];

? ? }


? ? void deallocate(RBTreeNode<T>* node) {

? ? ? ? // 簡(jiǎn)單的內(nèi)存池,實(shí)際可以更復(fù)雜

? ? }

};

```

## 總結(jié)

通過(guò)封裝紅黑樹(shù)實(shí)現(xiàn)mymap和myset容器,我們深入理解了關(guān)聯(lián)式容器的內(nèi)部機(jī)制。紅黑樹(shù)通過(guò)精妙的平衡策略,在各種操作場(chǎng)景下都能保持良好的性能表現(xiàn)。

實(shí)現(xiàn)過(guò)程中需要注意的關(guān)鍵點(diǎn)包括:旋轉(zhuǎn)操作的正確處理、插入刪除后的平衡調(diào)整、迭代器的正確實(shí)現(xiàn)以及內(nèi)存管理的優(yōu)化。這種底層實(shí)現(xiàn)的理解對(duì)于編寫(xiě)高性能的C++程序和深入理解標(biāo)準(zhǔn)庫(kù)容器具有重要意義。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容