跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 基于红黑树模拟实现 STL 的 map 和 set

综述由AI生成通过复用红黑树数据结构,在 C++ 中模拟实现了标准模板库(STL)的 map 和 set。内容涵盖红黑树的泛型改造以支持不同键值类型,迭代器 ++ 和 -- 操作的实现,以及插入时的平衡调整逻辑。代码展示了完整的 RBTree 类定义及 Set、Map 的封装测试,包括节点结构、旋转方法、变色规则及树合法性验证流程。

KernelLab发布于 2026/3/15更新于 2026/6/230 浏览
C++ 基于红黑树模拟实现 STL 的 map 和 set

一。红黑树的改造

map 和 set 底层都是通过红黑树实现的,但是 set 中存放的是 key,map 中为 key,value。我们不会去写两棵红黑树来实现它们,因为代码会重复,需要对红黑树内部进行改造。

template<class K,class T,class KOfT>

为了可以同时处理 set 和 map,传一个 T 过去,是 set 的时候为 key,map 为 pair<K,V>。

对于 set 和 map 他们的排序,set 可以直接通过 key 来排序,而 map 的排序规则与 set 不同,先比较 key,如果相同比较 value,所以传一个 KOfT。

struct SetKeyOfT { const K& operator()(const K& k) { return k; } };
struct MapKeyOfT { const K& operator()(const pair<K, V>& kv) { return kv.first; } };

通过 KOfT 来分别处理 set 和 map 的排序。

红黑树的迭代器

iterator begin() { Node* cur = _root; while (cur && cur->_left) { cur = cur->_left; } return iterator(cur); }
iterator end() { return iterator(nullptr); }

operator++ 与 operator--

Self& operator++() {
    // 如果右不为空,中序的下一个就是右子树的最左节点
    // 如果右为空,表示_node 所在子树访问完,下一个节点在他的祖先中找
    if (_node->_right) {
        Node* subLeft = _node->_right;
        while (subLeft->_left) { subLeft = subLeft->_left; }
        _node = subLeft;
    } else {
        Node* cur = _node;
        Node* parent = cur->_parent;
        while (parent && cur == parent->_right) {
            cur = cur->_parent;
            parent = parent->_parent;
        }
        _node = parent;
    }
    return *this;
}
Self& operator--() {
    // 与++基本相反
    return *this;
}

set 和 map 的实现都是对红黑树的复用,所以理解红黑树是关键。

二。模拟实现 set

set 的实现通过对红黑树的复用即可完成。

template<class K>
class set {
    struct SetKeyOfT {
        const K& operator()(const K& k) { return k; }
    };
public:
    typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
    iterator begin() { return _t.begin(); }
    iterator end() { return _t.end(); }
    pair<iterator, bool> Insert(const K& k) { return _t.Insert(k); }
private:
    RBTree<K, K, SetKeyOfT> _t;
};

三。模拟实现 map

template<class K,class V>
class map {
    struct MapKeyOfT {
        const K& operator()(const pair<K, V>& kv) { return kv.first; }
    };
public:
    typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
    iterator begin() { return _t.begin(); }
    iterator end() { return _t.end(); }
    pair<iterator, bool> Insert(const pair<K, V>& kv) { return _t.Insert(kv); }
    V& operator[](const K& key) {
        pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
        return ret.first->second;
    }
private:
    RBTree<K, pair<K, V>, MapKeyOfT> _t;
};

四。整体代码

1.RBTree.h

#pragma once
enum Colour { BLACK, RED, };

template<class T>
struct RBTreeNode {
    RBTreeNode<T>* _left;
    RBTreeNode<T>* _right;
    RBTreeNode<T>* _parent;
    T _data;
    Colour _col;
    RBTreeNode(const T& data) :_left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _col(RED) { };
};

template<class T, class Ref, class Ptr>
struct __TreeIterator {
    typedef RBTreeNode<T> Node;
    typedef __TreeIterator<T, Ref, Ptr> Self;
    Node* _node;
    __TreeIterator(Node* node) :_node(node) { }
    Ref operator*() { return _node->_data; }
    Ptr operator->() { return &_node->_data; }
    Self& operator++() {
        if (_node->_right) {
            Node* subLeft = _node->_right;
            while (subLeft->_left) { subLeft = subLeft->_left; }
            _node = subLeft;
        } else {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_right) {
                cur = cur->_parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }
    Self& operator--() {
        return *this;
    }
    bool operator !=(const Self& s) { return _node != s._node; }
    bool operator ==(const Self& s) { return _node == s._node; }
};

template<class K,class T,class KOfT>
class RBTree {
    typedef RBTreeNode<T> Node;
public:
    typedef __TreeIterator<T, T&, T*> iterator;
    typedef __TreeIterator<T, const T&, const T*> const_iterator;
    iterator begin() { Node* cur = _root; while (cur && cur->_left) { cur = cur->_left; } return iterator(cur); }
    iterator end() { return iterator(nullptr); }
    pair<iterator, bool> Insert(const T& data) {
        if (_root == nullptr) {
            _root = new Node(data);
            _root->_col = BLACK;
            return make_pair(iterator(_root), true);
        }
        KOfT koft;
        Node* parent = nullptr;
        Node* cur = _root;
        while (cur) {
            if (koft(cur->_data) < koft(data)) {
                parent = cur;
                cur = cur->_right;
            } else if (koft(cur->_data) > koft(data)) {
                parent = cur;
                cur = cur->_left;
            } else {
                return make_pair(iterator(cur), false);
            }
        }
        cur = new Node(data);
        Node* newnode = cur;
        if (koft(parent->_data) < koft(cur->_data)) {
            parent->_right = cur;
            cur->_parent = parent;
        } else {
            parent->_left = cur;
            cur->_parent = parent;
        }
        cur->_col = RED;
        while (parent && parent->_col == RED) {
            Node* grandfather = parent->_parent;
            if (grandfather->_left == parent) {
                Node* uncle = grandfather->_right;
                if (uncle && uncle->_col == RED) {
                    parent->_col = uncle->_col = BLACK;
                    grandfather->_col = RED;
                    cur = grandfather;
                    parent = cur->_parent;
                } else {
                    if (cur == parent->_right) {
                        RotateL(parent);
                        swap(parent, cur);
                    }
                    RotateR(grandfather);
                    grandfather->_col = RED;
                    parent->_col = BLACK;
                    break;
                }
            } else {
                Node* uncle = grandfather->_left;
                if (uncle && uncle->_col == RED) {
                    parent->_col = uncle->_col = BLACK;
                    grandfather->_col = RED;
                    cur = grandfather;
                    parent = cur->_parent;
                } else {
                    if (cur == parent->_left) {
                        RotateR(parent);
                        swap(parent, cur);
                    }
                    RotateL(grandfather);
                    grandfather->_col = RED;
                    parent->_col = BLACK;
                    break;
                }
            }
        }
        _root->_col = BLACK;
        return make_pair(iterator(newnode), true);
    }
    void RotateL(Node* parent) {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        parent->_right = subRL;
        if (subRL) subRL->_parent = parent;
        subR->_left = parent;
        Node* ppNode = parent->_parent;
        parent->_parent = subR;
        if (_root == parent) {
            _root = subR;
            subR->_parent = nullptr;
        } else {
            if (ppNode->_left == parent) ppNode->_left = subR;
            else ppNode->_right = subR;
            subR->_parent = ppNode;
        }
    }
    void RotateR(Node* parent) {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        parent->_left = subLR;
        if (subLR) subLR->_parent = parent;
        subL->_right = parent;
        Node* ppNode = parent->_parent;
        parent->_parent = subL;
        if (_root == parent) {
            _root = subL;
            subL->_parent = nullptr;
        } else {
            if (ppNode->_left == parent) ppNode->_left = subL;
            else ppNode->_right = subL;
            subL->_parent = ppNode;
        }
    }
    void _InOrder(Node* root) {
        if (root == nullptr) return;
        _InOrder(root->_left);
        cout << root->_data << endl;
        _InOrder(root->_right);
    }
    void InOrder() { _InOrder(_root); }
    bool IsValidRBTree() {
        Node* pRoot = _root;
        if (nullptr == pRoot) return true;
        if (BLACK != pRoot->_col) {
            cout << "违反红黑树性质:根节点必须为黑色" << endl;
            return false;
        }
        size_t blackCount = 0;
        Node* pCur = pRoot;
        while (pCur) {
            if (BLACK == pCur->_col) blackCount++;
            pCur = pCur->_left;
        }
        size_t k = 0;
        return _IsValidRBTree(pRoot, k, blackCount);
    }
    bool _IsValidRBTree(Node* pRoot, size_t k, const size_t blackCount) {
        if (nullptr == pRoot) {
            if (k != blackCount) {
                cout << "违反性质:每条路径中黑色节点的个数必须相同" << endl;
                return false;
            }
            return true;
        }
        if (BLACK == pRoot->_col) k++;
        Node* pParent = pRoot->_parent;
        if (pParent && RED == pParent->_col && RED == pRoot->_col) {
            cout << "违反性质:没有连在一起的红色节点" << endl;
            return false;
        }
        return _IsValidRBTree(pRoot->_left, k, blackCount) && _IsValidRBTree(pRoot->_right, k, blackCount);
    }
    iterator Find(const K& data) {
        KOfT koft;
        Node* cur = _root;
        while (cur) {
            if (koft(cur->_data) < koft(data)) {
                cur = cur->_right;
            } else if (koft(cur->_data) > koft(data)) {
                cur = cur->_left;
            } else {
                return iterator(cur);
            }
        }
        return iterator(nullptr);
    }
private:
    Node* _root = nullptr;
};

2.MySet.h

#pragma once
#include"RBTree.h"

template<class K>
class set {
    struct SetKeyOfT {
        const K& operator()(const K& k) { return k; }
    };
public:
    typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
    iterator begin() { return _t.begin(); }
    iterator end() { return _t.end(); }
    pair<iterator, bool> Insert(const K& k) { return _t.Insert(k); }
private:
    RBTree<K, K, SetKeyOfT> _t;
};

void test_set() {
    set<int> s;
    s.Insert(1);
    s.Insert(3);
    s.Insert(2);
    s.Insert(4);
    s.Insert(5);
    set<int>::iterator it = s.begin();
    while (it != s.end()) {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
    for (auto e : s) {
        cout << e << " ";
    }
    cout << endl;
}

3.MyMap.h

#pragma once
#include"RBTree.h"

template<class K,class V>
class map {
    struct MapKeyOfT {
        const K& operator()(const pair<K, V>& kv) { return kv.first; }
    };
public:
    typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
    iterator begin() { return _t.begin(); }
    iterator end() { return _t.end(); }
    pair<iterator, bool> Insert(const pair<K, V>& kv) { return _t.Insert(kv); }
    V& operator[](const K& key) {
        pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
        return ret.first->second;
    }
private:
    RBTree<K, pair<K, V>, MapKeyOfT> _t;
};

void test_map() {
    map<int, int> m;
    m.Insert(make_pair(1, 1));
    m.Insert(make_pair(2, 2));
    m.Insert(make_pair(4, 4));
    m.Insert(make_pair(3, 3));
    m.Insert(make_pair(5, 5));
    map<int, int>::iterator it = m.begin();
    while (it != m.end()) {
        cout << it->first << ":" << it->second << endl;
        ++it;
    }
    cout << endl;
    for (auto e : m) {
        cout << e.first << ":" << e.second << endl;
    }
    cout << endl;
    string strs[] = { "西瓜","苹果","西瓜", "葡萄", "西瓜", "橘子", "西瓜", "苹果", "西瓜", "橘子" };
    map<string, int> countmap;
    for (auto& str : strs) {
        countmap[str]++;
    }
    for (auto kv : countmap) {
        cout << kv.first << ":" << kv.second << endl;
    }
    cout << endl;
}

4.Test.cpp

#include<iostream>
using namespace std;
#include"MyMap.h"
#include"MySet.h"
int main() {
    test_map();
    test_set();
    return 0;
}

目录

  1. 一。红黑树的改造
  2. 二。模拟实现 set
  3. 三。模拟实现 map
  4. 四。整体代码
  5. 1.RBTree.h
  6. 2.MySet.h
  7. 3.MyMap.h
  8. 4.Test.cpp
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 为什么 VsCode 远程 Copilot 用不了 Claude Agent?系统权限不足的解决策略
  • 位运算实战:两整数之和与只出现一次的数字
  • AI 产品经理转行大模型指南:核心素质与学习路径
  • Flutter 2 迁移实践与空安全详解
  • Python 将元组组成的列表转换为字典
  • 无人机飞行空域申请全流程指南
  • 前端可访问性开发指南
  • SBUS 协议详解:从原理到代码实现(无人机/航模适用)
  • 后仿真 SDF 反标常见 Warning 分析与处理指南
  • 多智能体架构选型:四种模式与决策指南
  • LeetCode 128:哈希集合巧解最长连续序列
  • Linux 进程间通信进阶:管道与共享内存详解
  • .NET 集成 GoView 低代码可视化大屏实战指南
  • PyCharm 安装与基础配置指南
  • VLA 模型真实世界分布式在线后训练系统 SOP 解析
  • GitHub 学生开发者认证指南与配置流程
  • OpenClaw 本地部署指南:快速搭建自托管 AI 管家
  • ToDesk 发布 ToClaw:AI Agent 融入日常工作流
  • 本地深度学习环境搭建指南:硬件、系统与框架配置
  • GitHub Copilot 集成安全风险及防护实践

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online