map和set的应用与模拟实现

map 和 set 是 C++ 标准库中常用的关联式容器,均基于红黑树(自平衡二叉搜索树)实现

set(集合)

  • 存储内容:仅存储单一键值(key),且键值唯一(不允许重复元素)。
  • 核心特性:元素会按照默认的升序(或自定义比较器指定的规则)自动排序;插入重复元素时会被忽略。
  • 主要用途:用于存储不重复的元素集合,适合需要快速查找、去重或有序遍历的场景(如统计唯一元素、检查元素是否存在等)。
  • 常用操作insert()(插入)、erase()(删除)、find()(查找)、size()(元素数量)等。

map(映射)

  • 存储内容:存储键值对(key-value),其中 key 唯一(不能重复),value 为对应的数据。
  • 核心特性:按键(key)的默认升序(或自定义规则)排序;通过 key 可以快速访问对应的 value。
  • 主要用途:用于建立键与值的映射关系(如字典、索引表),适合需要通过唯一标识(key)查找关联数据(value)的场景(如存储学生 ID 与成绩的对应关系)。
  • 特殊操作:支持[]运算符(如map[key] = value),可直接通过 key 访问或插入 value;find()返回指向键值对的迭代器,通过->first获取 key,->second获取 value。

 红黑树的模拟实现

#ifndef RBTREE_H
#define RBTREE_H

#include <iostream>
#include <cassert>

// 红黑树节点颜色
enum Color { RED, BLACK };

// 红黑树节点模板类
template <typename T>
struct RBTreeNode {
    T data;
    RBTreeNode* left;
    RBTreeNode* right;
    RBTreeNode* parent;
    Color color;

    // 构造函数
    RBTreeNode(const T& val) 
        : data(val), left(nullptr), right(nullptr), parent(nullptr), color(RED) {}
};

// 红黑树模板类
template <typename T, typename Compare = std::less<T>>
class RBTree {
protected:
    using Node = RBTreeNode<T>;
    Node* root;
    Compare comp;
    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 == nil) {
            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 == nil) {
            root = x;
        } else if (y == y->parent->right) {
            y->parent->right = x;
        } else {
            y->parent->left = x;
        }

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

    // 插入后修复红黑树性质
    void insertFixup(Node* z) {
        while (z->parent->color == RED) {
            if (z->parent == z->parent->parent->left) {
                Node* y = z->parent->parent->right;  // 叔叔节点

                if (y->color == RED) {
                    // 情况1:叔叔是红色
                    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 {
                // 镜像情况:父节点是右孩子
                Node* y = z->parent->parent->left;  // 叔叔节点

                if (y->color == RED) {
                    // 情况1:叔叔是红色
                    z->parent->color = BLACK;
                    y->color = BLACK;
                    z->parent->parent->color = RED;
                    z = z->parent->parent;
                } else {
                    if (z == z->parent->left) {
                        // 情况2:叔叔是黑色,且z是左孩子
                        z = z->parent;
                        rightRotate(z);
                    }
                    // 情况3:叔叔是黑色,且z是右孩子
                    z->parent->color = BLACK;
                    z->parent->parent->color = RED;
                    leftRotate(z->parent->parent);
                }
            }
        }
        root->color = BLACK;  // 根节点始终为黑色
    }

    // 查找最小值节点
    Node* minimum(Node* node) const {
        while (node->left != nil) {
            node = node->left;
        }
        return node;
    }

    // 查找最大值节点
    Node* maximum(Node* node) const {
        while (node->right != nil) {
            node = node->right;
        }
        return node;
    }

    // 查找后继节点
    Node* successor(Node* x) const {
        if (x->right != nil) {
            return minimum(x->right);
        }

        Node* y = x->parent;
        while (y != nil && x == y->right) {
            x = y;
            y = y->parent;
        }
        return y;
    }

    // 删除后修复红黑树性质
    void deleteFixup(Node* x) {
        while (x != root && x->color == BLACK) {
            if (x == x->parent->left) {
                Node* w = x->parent->right;  // 兄弟节点

                if (w->color == RED) {
                    // 情况1:兄弟是红色
                    w->color = BLACK;
                    x->parent->color = RED;
                    leftRotate(x->parent);
                    w = x->parent->right;
                }

                if (w->left->color == BLACK && w->right->color == BLACK) {
                    // 情况2:兄弟是黑色,且两个孩子都是黑色
                    w->color = RED;
                    x = x->parent;
                } else {
                    if (w->right->color == BLACK) {
                        // 情况3:兄弟是黑色,左孩子红色,右孩子黑色
                        w->left->color = BLACK;
                        w->color = RED;
                        rightRotate(w);
                        w = x->parent->right;
                    }
                    // 情况4:兄弟是黑色,右孩子红色
                    w->color = x->parent->color;
                    x->parent->color = BLACK;
                    w->right->color = BLACK;
                    leftRotate(x->parent);
                    x = root;  // 退出循环
                }
            } else {
                // 镜像情况:x是右孩子
                Node* w = x->parent->left;  // 兄弟节点

                if (w->color == RED) {
                    // 情况1:兄弟是红色
                    w->color = BLACK;
                    x->parent->color = RED;
                    rightRotate(x->parent);
                    w = x->parent->left;
                }

                if (w->right->color == BLACK && w->left->color == BLACK) {
                    // 情况2:兄弟是黑色,且两个孩子都是黑色
                    w->color = RED;
                    x = x->parent;
                } else {
                    if (w->left->color == BLACK) {
                        // 情况3:兄弟是黑色,右孩子红色,左孩子黑色
                        w->right->color = BLACK;
                        w->color = RED;
                        leftRotate(w);
                        w = x->parent->left;
                    }
                    // 情况4:兄弟是黑色,左孩子红色
                    w->color = x->parent->color;
                    x->parent->color = BLACK;
                    w->left->color = BLACK;
                    rightRotate(x->parent);
                    x = root;  // 退出循环
                }
            }
        }
        x->color = BLACK;
    }

    // 从节点z开始删除
    void transplant(Node* u, Node* v) {
        if (u->parent == nil) {
            root = v;
        } else if (u == u->parent->left) {
            u->parent->left = v;
        } else {
            u->parent->right = v;
        }
        v->parent = u->parent;
    }

    // 递归销毁树
    void destroy(Node* node) {
        if (node != nil) {
            destroy(node->left);
            destroy(node->right);
            delete node;
        }
    }

    // 复制树
    Node* copyTree(Node* node, Node* parentNode) {
        if (node == nil) return nil;
        
        Node* newNode = new Node(node->data);
        newNode->color = node->color;
        newNode->parent = parentNode;
        newNode->left = copyTree(node->left, newNode);
        newNode->right = copyTree(node->right, newNode);
        
        return newNode;
    }

public:
    // 迭代器类
    class iterator {
    protected:
        Node* current;
        const RBTree* tree;
        friend class RBTree;

    public:
        using value_type = T;
        using reference = T&;
        using pointer = T*;
        using difference_type = std::ptrdiff_t;
        using iterator_category = std::bidirectional_iterator_tag;

        iterator(Node* node, const RBTree* t) : current(node), tree(t) {}

        reference operator*() const { return current->data; }
        pointer operator->() const { return &(current->data); }

        iterator& operator++() {
            current = tree->successor(current);
            return *this;
        }

        iterator operator++(int) {
            iterator temp = *this;
            ++(*this);
            return temp;
        }

        bool operator==(const iterator& other) const {
            return current == other.current;
        }

        bool operator!=(const iterator& other) const {
            return !(*this == other);
        }
    };

    // 构造函数
    RBTree() {
        nil = new Node(T());
        nil->color = BLACK;
        nil->left = nil->right = nil->parent = nil;
        root = nil;
    }

    // 拷贝构造函数
    RBTree(const RBTree& other) {
        nil = new Node(T());
        nil->color = BLACK;
        nil->left = nil->right = nil->parent = nil;
        root = copyTree(other.root, nil);
        comp = other.comp;
    }

    // 赋值运算符
    RBTree& operator=(const RBTree& other) {
        if (this != &other) {
            destroy(root);
            root = copyTree(other.root, nil);
            comp = other.comp;
        }
        return *this;
    }

    // 析构函数
    ~RBTree() {
        destroy(root);
        delete nil;
    }

    // 插入元素
    std::pair<iterator, bool> insert(const T& val) {
        Node* z = new Node(val);
        Node* y = nil;
        Node* x = root;

        // 查找插入位置
        while (x != nil) {
            y = x;
            if (comp(z->data, x->data)) {
                x = x->left;
            } else if (comp(x->data, z->data)) {
                x = x->right;
            } else {
                // 元素已存在,返回已存在的迭代器和false
                delete z;
                return {iterator(x, this), false};
            }
        }

        z->parent = y;
        if (y == nil) {
            root = z;  // 树为空,z成为根节点
        } else if (comp(z->data, y->data)) {
            y->left = z;
        } else {
            y->right = z;
        }

        z->left = nil;
        z->right = nil;
        z->color = RED;

        insertFixup(z);  // 修复红黑树性质

        return {iterator(z, this), true};
    }

    // 删除元素
    bool erase(const T& val) {
        Node* z = nil;
        Node* x = root;

        // 查找要删除的节点
        while (x != nil) {
            if (comp(val, x->data)) {
                x = x->left;
            } else if (comp(x->data, val)) {
                x = x->right;
            } else {
                z = x;
                break;
            }
        }

        if (z == nil) {
            return false;  // 元素不存在
        }

        Node* y = z;
        Node* x = nil;
        Color yOriginalColor = y->color;

        if (z->left == nil) {
            x = z->right;
            transplant(z, z->right);
        } else if (z->right == nil) {
            x = z->left;
            transplant(z, z->left);
        } else {
            y = minimum(z->right);
            yOriginalColor = y->color;
            x = y->right;

            if (y->parent == z) {
                x->parent = y;
            } else {
                transplant(y, y->right);
                y->right = z->right;
                y->right->parent = y;
            }

            transplant(z, y);
            y->left = z->left;
            y->left->parent = y;
            y->color = z->color;
        }

        delete z;

        if (yOriginalColor == BLACK) {
            deleteFixup(x);  // 修复红黑树性质
        }

        return true;
    }

    // 查找元素
    iterator find(const T& val) const {
        Node* x = root;
        while (x != nil) {
            if (comp(val, x->data)) {
                x = x->left;
            } else if (comp(x->data, val)) {
                x = x->right;
            } else {
                return iterator(x, this);  // 找到元素
            }
        }
        return end();  // 未找到元素
    }

    // 清空树
    void clear() {
        destroy(root);
        root = nil;
    }

    // 判断树是否为空
    bool empty() const {
        return root == nil;
    }

    // 迭代器起始位置
    iterator begin() const {
        if (empty()) return end();
        return iterator(minimum(root), this);
    }

    // 迭代器结束位置
    iterator end() const {
        return iterator(nil, this);
    }
};

#endif // RBTREE_H

 set的模拟实现

#ifndef SET_H
#define SET_H

#include "rbtree.h"

// set模板类
template <typename Key, typename Compare = std::less<Key>>
class set {
public:
    using key_type = Key;
    using value_type = Key;
    using reference = value_type&;
    using const_reference = const value_type&;
    using size_type = size_t;
    using difference_type = std::ptrdiff_t;
    using compare = Compare;

private:
    using Tree = RBTree<value_type, Compare>;
    Tree tree;

public:
    // 迭代器类型
    using iterator = typename Tree::iterator;
    
    // 构造函数
    set() : tree() {}
    
    // 拷贝构造函数
    set(const set& other) : tree(other.tree) {}
    
    // 赋值运算符
    set& operator=(const set& other) {
        if (this != &other) {
            tree = other.tree;
        }
        return *this;
    }
    
    // 插入元素
    std::pair<iterator, bool> insert(const value_type& val) {
        return tree.insert(val);
    }
    
    // 删除元素
    bool erase(const value_type& val) {
        return tree.erase(val);
    }
    
    // 查找元素
    iterator find(const value_type& val) {
        return tree.find(val);
    }
    
    // 清空set
    void clear() {
        tree.clear();
    }
    
    // 判断set是否为空
    bool empty() const {
        return tree.empty();
    }
    
    // 迭代器起始位置
    iterator begin() {
        return tree.begin();
    }
    
    // 迭代器结束位置
    iterator end() {
        return tree.end();
    }
};

#endif 

 map的模拟实现

#ifndef MAP_H
#define MAP_H

#include "rbtree.h"
#include <utility>

// 用于map的键值对比较器
template <typename Key, typename T, typename Compare>
struct PairCompare {
    Compare comp;
    
    bool operator()(const std::pair<Key, T>& a, const std::pair<Key, T>& b) const {
        return comp(a.first, b.first);
    }
};

// map模板类
template <typename Key, typename T, typename Compare = std::less<Key>>
class map {
public:
    using key_type = Key;
    using mapped_type = T;
    using value_type = std::pair<key_type, mapped_type>;
    using reference = value_type&;
    using const_reference = const value_type&;
    using size_type = size_t;
    using difference_type = std::ptrdiff_t;
    using compare = Compare;

private:
    using Tree = RBTree<value_type, PairCompare<Key, T, Compare>>;
    Tree tree;

public:
    // 迭代器类型
    using iterator = typename Tree::iterator;
    
    // 构造函数
    map() : tree() {}
    
    // 拷贝构造函数
    map(const map& other) : tree(other.tree) {}
    
    // 赋值运算符
    map& operator=(const map& other) {
        if (this != &other) {
            tree = other.tree;
        }
        return *this;
    }
    
    // 插入元素
    std::pair<iterator, bool> insert(const value_type& val) {
        return tree.insert(val);
    }
    
    // 删除元素
    bool erase(const key_type& key) {
        return tree.erase(value_type(key, mapped_type()));
    }
    
    // 查找元素
    iterator find(const key_type& key) {
        return tree.find(value_type(key, mapped_type()));
    }
    
    // 访问或插入元素
    mapped_type& operator[](const key_type& key) {
        std::pair<iterator, bool> result = tree.insert(value_type(key, mapped_type()));
        return result.first->second;
    }
    
    // 清空map
    void clear() {
        tree.clear();
    }
    
    // 判断map是否为空
    bool empty() const {
        return tree.empty();
    }
    
    // 迭代器起始位置
    iterator begin() {
        return tree.begin();
    }
    
    // 迭代器结束位置
    iterator end() {
        return tree.end();
    }
};

#endif 

 

总的来说,set 专注于元素的唯一性和有序性

ma专注于通过键快速访问对应的值

两者均依赖红黑树实现,因此具备有序性和高效的平衡操作

 


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值