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

STL 容器 map 与 set 的红黑树封装及迭代器实现原理

STL 容器 map 和 set 基于红黑树封装。map 存储键值对,set 存储单一元素去重排序。通过 KeyOfT 提取键进行排序,控制迭代器权限防止非法修改。红黑树模拟实现包含节点定义、插入平衡(变色旋转)、查找功能。迭代器支持 ++/-- 操作,右子树找最左或回溯父节点。代码展示了自定义命名空间下的完整结构体与函数实现,涵盖 begin/end 定位及内存管理细节。

www发布于 2026/3/22更新于 2026/8/337 浏览
STL 容器 map 与 set 的红黑树封装及迭代器实现原理

概述

STL 中的 map 和 set 本质上是对红黑树的定制化封装。红黑树作为通用骨架,通过提取键的规则(KeyOfT)、迭代器权限控制以及键值修改限制,分别适配了'键值对存储'和'单一元素去重排序'的需求。

map 和 set 的封装差异

在封装时,对红黑树内部 K(Key)和 T(Value)的处理有所不同:

  • map: K 存储 Key,T 存储 pair<Key, Value>。K 用于排序查找,Value 用于存信息。K 不可修改,Value 可修改。
  • set: K 存储 Key,T 也存储 Key。两者相同,主要用于去重和排序。K 和 T 均不可修改。

map 实现示例

namespace stl_impl {
template<class K, class V>
class map {
    struct MapKeyOfT {
        const K& operator()(const std::pair<K, V>& kv) {
            return kv.first;
        }
    };
public:
    typedef typename RBTree<K, std::pair<const K, V>, MapKeyOfT>::iterator iterator;
    typedef typename RBTree<K, std::pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;

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

    V& []( K& key) {
        std::pair<iterator, > ret = (std::(key, ()));
         ret.first->second;
    }

    {
         .(kv);
    }

:
    RBTree<K, std::pair< K, V>, MapKeyOfT> ;
};
}
return
_t
begin
const_iterator end() const
return
_t
end
operator
const
bool
insert
make_pair
V
return
std::pair<iterator, bool> insert(const std::pair<K, V>& kv)
return
_t
Insert
private
const
_t

set 实现示例

namespace stl_impl {
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(); }

    std::pair<iterator, bool> insert(const K& key) {
        std::pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
        return std::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;
    }

    std::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 {
                    // u 不存在 或 存在且为黑
                    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;
    // 旋转相关代码参考 AVL 树实现
    void RotateL(Node* parent) {} // Placeholder
    void RotateR(Node* parent) {} // Placeholder
};

注意:需区分头节点与根节点。库实现中通常包含头节点,其父亲是红黑树根节点,left 指向最小数,right 指向最大数。

迭代器模拟实现

迭代器的 begin 指向最左节点,end 指向 nullptr(逻辑上的尾后位置)。

++ 操作逻辑

  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->_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--() {
        if (_node->_left) {
            Node* subRight = _node->_left;
            while (subRight->_right) {
                subRight = subRight->_right;
            }
            _node = subRight;
        } else {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_left) {
                cur = cur->_parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }
};

目录

  1. 概述
  2. map 和 set 的封装差异
  3. map 实现示例
  4. set 实现示例
  5. 红黑树模拟实现
  6. 迭代器模拟实现
  7. ++ 操作逻辑
  8. -- 操作逻辑
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 机器人操作 VLA 模型强化学习综述
  • 4G Cat.1模组赋能AI教育机器人:政策驱动下的算力与物联网机遇
  • Coze 平台全解析:100 个落地场景与发布指南
  • Kubernetes与AI推理服务最佳实践
  • Paperzz 论文降重与 AIGC 检测功能分析
  • 前端状态管理:Recoil的原子世界
  • AIGCJson 库源码解析:宏与模板实现的 JSON 序列化
  • MySQL MVCC 多版本并发控制原理
  • Pico 4XVR 1.10.13 安装与使用指南
  • Linux 网络编程:使用 C++ 实现基于 JSON 和 HTTP 的 Web 计算器服务器
  • 设计模式实战:过滤器模式(Criteria Pattern)详解
  • Python 中的多线程是什么?如何实现?
  • Whisper-large-v3-turbo 深度解析:8 倍速语音识别技术
  • Spring 事务及其传播机制详解
  • 基于 B/S 架构的 Web 化医疗影像系统 (PACS/RIS) 技术解析
  • C++ 与 ROS 中 int main(int argc, char* argv[]) 的区别
  • AI 大模型通信机制解析:流式传输与数据封装逻辑
  • 低成本运行 Claude Code:通过 LiteLLM 接入 GitHub Copilot Chat API
  • 网络安全行业发展前景与零基础转行建议
  • 飞算 Java 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