跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++算法

STL 底层解析:map 与 set 基于红黑树的封装及迭代器实现

STL 标准库中 map 和 set 容器基于红黑树数据结构实现。map 存储键值对,set 存储唯一键。通过 KeyOfT 策略函数提取键值进行比较排序。迭代器实现支持前向和后向遍历,利用右子树最左节点或父节点回溯逻辑完成 ++ 和 -- 操作。代码示例包含红黑树节点定义、插入时的颜色调整与旋转平衡算法,以及迭代器的指针操作符重载。

热情发布于 2026/3/26更新于 2026/5/118 浏览
STL 底层解析:map 与 set 基于红黑树的封装及迭代器实现

map 和 set 的封装

这俩在封装的时候对红黑树里面的 K,T 的处理:

map的话 K 是存 Key,T 是搞的 pair<Key,Value>--这两个 Key 是一样的哈

set的话 K 是存 Key,T 也是存 Key--这两个 Key 是一样的哈 (第二个 T 存东西单纯为了陪跑)

对于 set的话 KT 都不能被修改–因为都是 Key

对于 map的话 K 不能被修改,T 里面的 value 可以被修改

对于键和值的理解:

对于 map:键用来排序查找啥的,值用来存信息

对于 set:键承担了所有

namespace mylib {
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<const K, V>, MapKeyOfT>::iterator iterator;
    typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;

    iterator begin() {
        return _t.begin();
    }
    iterator end() {
        return _t.end();
    }
    const_iterator begin() const {
        return _t.begin();
    }
    const_iterator end() const {
        return _t.end();
    }

    V& operator[](const K& key) {
        pair<iterator, bool> ret = insert(make_pair(key, V()));
        return ret.first->second;
    }

    pair<iterator, bool> insert(const pair<K, V>& kv) {
        return _t.Insert(kv);
    }

private:
    RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
}

map的 []可以插入和修改和访问–string的 []不能用来插入

namespace mylib {
template <class K>
class set {
    struct SetKeyOfT {
        const K& operator()(const K& key) {
            return key;
        }
    };
public:
    typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
    typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;

    const_iterator begin() const {
        return _t.begin();
    }
    const_iterator end() const {
        return _t.end();
    }

    pair<iterator, bool> insert(const K& key) {
        pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
        return pair<iterator, bool>(ret.first, ret.second);
    }

private:
    RBTree<K, K, SetKeyOfT> _t;
};
}

底层红黑树的模拟实现

enum Colour { RED, BLACK };

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 K, class T, class KeyOfT>
struct RBTree {
    typedef RBTreeNode<T> Node;

public:
    typedef __TreeIterator<T, T*, T&> iterator;
    typedef __TreeIterator<T, const T*, const T&> const_iterator;

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

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

    const_iterator begin() const {
        Node* leftMin = _root;
        while (leftMin && leftMin->_left) {
            leftMin = leftMin->_left;
        }
        return const_iterator(leftMin);
    }

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

    Node* Find(const K& key) {
        Node* cur = _root;
        KeyOfT kot;
        while (cur) {
            if (kot(cur->_data) < key) {
                cur = cur->_right;
            } else if (kot(cur->_data) > key) {
                cur = cur->_left;
            } else {
                return cur;
            }
        }
        return nullptr;
    }

    pair<iterator, bool> Insert(const T& data) {
        if (_root == nullptr) {
            _root = new Node(data);
            _root->_col = BLACK;
            return make_pair(iterator(_root), true);
        }

        Node* parent = nullptr;
        Node* cur = _root;
        KeyOfT kot;
        while (cur) {
            if (kot(cur->_data) < kot(data)) {
                parent = cur;
                cur = cur->_right;
            } else if (kot(cur->_data) > kot(data)) {
                parent = cur;
                cur = cur->_left;
            } else {
                return make_pair(iterator(cur), false);
            }
        }

        cur = new Node(data);
        cur->_col = RED;
        if (kot(parent->_data) < kot(data)) {
            parent->_right = cur;
        } else {
            parent->_left = cur;
        }
        cur->_parent = parent;

        while (parent && parent->_col == RED) {
            Node* grandfather = parent->_parent;
            if (parent == grandfather->_left) {
                Node* uncle = grandfather->_right;
                // u 存在且为红
                if (uncle && uncle->_col == RED) {
                    parent->_col = uncle->_col = BLACK;
                    grandfather->_col = RED;
                    cur = grandfather;
                    parent = cur->_parent;
                } else {
                    if (cur == parent->_left) {
                        RotateR(grandfather);
                        parent->_col = BLACK;
                        grandfather->_col = RED;
                    } else {
                        RotateL(parent);
                        RotateR(grandfather);
                        cur->_col = BLACK;
                        grandfather->_col = RED;
                    }
                    break;
                }
            } else {
                Node* uncle = grandfather->_left;
                // u 存在且为红
                if (uncle && uncle->_col == RED) {
                    parent->_col = uncle->_col = BLACK;
                    grandfather->_col = RED;
                    cur = grandfather;
                    parent = cur->_parent;
                } else {
                    if (cur == parent->_right) {
                        RotateL(grandfather);
                        grandfather->_col = RED;
                        parent->_col = BLACK;
                    } else {
                        RotateR(parent);
                        RotateL(grandfather);
                        cur->_col = BLACK;
                        grandfather->_col = RED;
                    }
                    break;
                }
            }
        }
        _root->_col = BLACK;
        return make_pair(iterator(cur), true);
    }

private:
    Node* _root = nullptr;
};

库里面的红黑树和这里的模拟实现的区别:

库里面其实还有个头节点,头节点的父亲是红黑树的根节点,头节点的 left 是红黑树里面最小的数,头节点的 right 是红黑树里面最大的数,然后根节点的父亲也是头节点

注意:区分头节点和根节点!

迭代器的模拟实现

这里的迭代器的 begin和 end的位置要注意:

begin是最左边的那个节点

end是根节点的父亲–nullptr–这个 begin和 end是在底层红黑树那里定义的

这里的迭代器的 ++:

1.当前节点的右子树不为空,则访问右树的最左节点

2.当前节点的右子树为空,如果当前节点的父亲是其父亲的左孩子,就访问当前节点的父亲,不然就把当前节点的父亲变成当前节点,直到遇到那种情况或者当前节点成根节点的父亲了

这里迭代器的 --:

1.当前节点的左子树不为空,则访问左树的最右节点

2.当前节点的右子树为空,如果当前节点的父亲是其父亲的右孩子,就访问当前节点的父亲,不然就把当前节点的父亲变成当前节点,直到遇到那种情况或者当前节点变成根节点的父亲了

引申:普通迭代器可以隐式转换为 const 迭代器

template <class T, class Ptr, class Ref>
struct __TreeIterator {
    typedef RBTreeNode<T> Node;
    typedef __TreeIterator<T, Ptr, Ref> Self;
    typedef __TreeIterator<T, T*, T&> Iterator;

    __TreeIterator(const Iterator& it) : _node(it._node) {}
    Node* _node;

    __TreeIterator(Node* node) : _node(node) {}

    Ref operator*() {
        return _node->_data;
    }

    Ptr operator->() {
        return &_node->_data;
    }

    bool operator!=(const Self& s) const {
        return _node != s._node;
    }

    bool operator==(const Self& s) const {
        return _node == s._node;
    }

    Self& operator--() {
        if (_node->_left) {
            Node* subNode = _node->_left;
            while (subNode->_right) {
                subNode = subNode->_right;
            }
            _node = subNode;
        } else {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_left) {
                cur = cur->_parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }

    Self& operator++() {
        if (_node->_right) {
            Node* subNode = _node->_right;
            while (subNode->_left) {
                subNode = subNode->_left;
            }
            _node = subNode;
        } else {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_right) {
                cur = cur->_parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }
};

目录

  1. map 和 set 的封装
  2. 底层红黑树的模拟实现
  3. 迭代器的模拟实现
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 电科金仓发布融合数据库,定义 AI 时代新形态
  • C++11 右值引用与移动语义详解:从性能瓶颈到零拷贝优化
  • OpenClaw + Ollama 本地部署实战指南
  • HarmonyOS NEXT 静默登录与多维数据同步体系构建
  • 使用 Higress 网关将 REST API 转换为 MCP Server 工具
  • C 语言初阶算法习题实战解析
  • 金仓数据库 SQL 防火墙:SQL 注入拦截原理与性能测试
  • PyTorch 生成式人工智能:StyleGAN 详解与实现
  • 可控大模型应用框架 simple_ai_toolset
  • 手把手实现 STL Set/Map:从零编写一棵红黑树到完整容器封装
  • Linux 线程概念与 pthread 接口入门
  • Java 快速开发框架实战对比:若依、芋道、Jeesite、JeecgBoot
  • Leaflet 与 SpringBoot 实现地图点击获取当地时间
  • AI 辅助开发:基于 DeepSeek 构建贪吃蛇游戏实战
  • Dify Web 前端二次开发:隐藏探索功能与替换 Logo
  • π0.5 开源:Physical Intelligence GitHub 仓库 9 月更新
  • Whisper-large-v3 与 FunASR 技术选型与性能调优
  • Windows 下安装 OpenClaw 并接入飞书机器人
  • 2024 年 3 月编程语言排行榜:Python 领先优势显著
  • Spring Cloud+AI :实现分布式智能推荐系统

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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