STL容器之map和set的补充——map与set的封装

一、模拟实现map和set

1.1三个类模板的设计

template <class Key, class Value, class KeyOfValue, class Compare,
          class Alloc = alloc>class rb_tree{};//红黑树类模板

template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map{};//map对红黑树进行了封装
template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set{};//set对红黑树进行了封装

​ 实际上红黑树类模板的第二个模板参数决定了红黑树的节点用来存放key还是pair;第一个模板参数是因为find之类的函数需要传递key,而第二个模板参数可能是pair无法实现实现直接使用key进行比较;第三个模板参数是为了解决insert是需要根据键值来进行搜索二叉树的建立,但是传递的参数是data,可能是键值,也可能是pair,所以需要使用仿函数,将key取出来,主要是为了map设计的;

​ 为什么不使用仿函数直接比较而是返回key值,因为仿函数是最外层进行传入的,最外层传递比较方式,而内层的红黑树关心的是键值比较,所以红黑树使用KeyOfT;

1.2迭代器的设计

在rbtree中设计。

1.2.1begin/end

​ begin返回值是最左节点,end返回的是nullptr;

​ 而库里面实现的是增加了一个哨兵位,使得哨兵位的左指向最小值,右指向最大值,end是哨兵位;好处是获取begin较快,但是删除和插入的成本增加了;

1.2.2++和- -的设计

​ ++走中序遍历;

​ 1.右不为空,访问右树的最左节点;

​ 2.右为空,访问满足孩子是父亲的左孩子的最近祖先;

​ - - 反的走中序遍历

​ 1.左不为空,访问左树的最右节点;

​ 2.左为空,访问满足孩子是父亲的右孩子的最近祖先;

1.2.3const迭代器

​ RBTree通过模板参数实现const的迭代器类,set封装使用const迭代器来定义普通和const迭代器,即set使用的迭代器都是const迭代器;map使用pair<const K,V>来实现普通的迭代器不可以访问key;

1.2.4反向迭代器

1.3插入实现

​ 注意返回值是pair,要注意对于set返回值要使用const迭代器的构造(普通迭代器对const迭代器的构造),因为普通迭代器和const迭代器会发生冲突;

​ 对于tree迭代器类的设计其实是设计了一个迭代器的拷贝构造函数,set调用时变成普通迭代器对const迭代器的构造;然后tree迭代器内嵌了普通迭代器的类型。对于内嵌类型类外使用时不会给提示的,还必须typename修饰。

1.4operator[]

​ 使用insert实现。

1.5map,tree,set的代码实现

namespace RbTree
{
    enum Colour
    {
        RED,
        BLACK,
    };
    template <class T>
    struct RBTreeNode
    {
        RBTreeNode(const T &data) : data_(data), left_(nullptr), right_(nullptr), parent_(nullptr), col_(RED) {}
        T data_;
        RBTreeNode<T> *left_;
        RBTreeNode<T> *right_;
        RBTreeNode<T> *parent_;
        Colour col_;
    };
    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(node *node = nullptr) : node_(node) {}
        __TreeIterator(const iterator &it) : node_(nullptr)
        {
            node_ = it.node_;
        }
        Ref operator*()
        {
            return node_->data_;
        }
        Ptr operator->()
        {
            return &(node_->data_);
        }
        Self &operator++()
        {
            if (node_->right_)
            {
                // 右不为空,访问右树的最左节点
                node *subleft = node_->right_;
                while (subleft->left_)
                {
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值