前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++精通之路:模拟实现map\u002Fset

C++精通之路:模拟实现map\u002Fset

作者头像
雪芙花
发布2022-10-31 18:17:39
1570
发布2022-10-31 18:17:39
举报
文章被收录于专栏:雪芙花雪芙花

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情

这篇是红黑树整体的模拟实现和讲解

一:红黑树的封装与适配

  • 代码:
代码语言:javascript
复制
//颜色
enum Colour
{
    RED,
    BLACK,
};

template<class T>
struct RBTreeNode
{
    RBTreeNode<T>* _left;
    RBTreeNode<T>* _right;
    RBTreeNode<T>* _parent;

    T _data;//T可以是key也可以是pair<K,V>
    Colour _col;

    RBTreeNode(const T&amp; data)
        :_left(nullptr)
        , _right(nullptr)
        , _parent(nullptr)
        , _data(data)
        , _col(RED)
    {}
};

template<class K, class T, class KeyOfT>
class RBTree
{
    typedef RBTreeNode<T> Node;
public:
    typedef _TreeIterator<T, T&amp;, T*> iterator;
    typedef _TreeIterator<T,const T&amp;, const T*> const_iterator;
    typedef ReverseIterator<iterator> reverse_iterator;
    typedef ReverseIterator<const_iterator> reverse_const_iterator;

    RBTree()
        :_root(nullptr)
    {}

    ~RBTree()
    {
        _Destory(_root);
    }

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

    reverse_iterator rbegin()
    {
        Node* cur = _root;
        while (cur&amp;&amp;cur->_right)
        {
            cur = cur->_right;
        }
        return reverse_iterator(iterator(cur));
    }

    reverse_iterator rend()
    {
        return reverse_iterator(iterator(nullptr));
    }

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

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

    pair<iterator, bool> Insert(const T&amp; data)
    {
        //空树的情况
        if (_root == nullptr)
        {
            _root = new Node(data);
            _root->_col = BLACK;
            return make_pair(iterator(_root), true);
        }
        KeyOfT kot;
        //查找位置插入节点
        Node* cur = _root, * parent = _root;
        while (cur)
        {
            if (kot(cur->_data) > kot(data))
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (kot(cur->_data) < kot(data))
            {
                parent = cur;
                cur = cur->_right;
            }
            else
            {
                return make_pair(iterator(cur), false);
            }
        }

        //创建链接节点
        cur = new Node(data);
        Node* newnode = cur;
        if (kot(parent->_data) > kot(data))
        {
            parent->_left = cur;
        }
        else
        {
            parent->_right = cur;
        }
        cur->_parent = parent;

        //父节点存在且为红,则需要调整(不能存在连续的红色节点)
        while (parent &amp;&amp; parent->_col == RED)
        {
            //此时当前节点一定有祖父节点
            Node* granparent = parent->_parent;
            //具体调整情况主要看叔叔节点
            //分左右讨论
            if (parent == granparent->_left)
            {
                Node* uncle = granparent->_right;
                //情况1:叔叔节点存在且为红
                if (uncle &amp;&amp; uncle->_col == RED)
                {
                    //修改颜色,继续向上检查
                    granparent->_col = RED;
                    parent->_col = uncle->_col = BLACK;

                    cur = granparent;
                    parent = cur->_parent;
                }
                else//情况2和3:叔叔节点不存在 或者存在且为黑
                {
                    //单旋(三代节点为斜线)+变色
                    if (cur == parent->_left)
                    {
                        RotateR(granparent);

                        granparent->_col = RED;
                        parent->_col = BLACK;
                    }
                    else//双旋(三代节点为折线)+变色
                    {
                        RotateL(parent);
                        RotateR(granparent);

                        cur->_col = BLACK;
                        granparent->_col = RED;
                    }
                    //旋转后不需再向上调整了
                    break;
                }
            }
            else//parent=grandparent->right
            {
                Node* uncle = granparent->_left;
                if (uncle &amp;&amp; uncle->_col == RED)
                {
                    parent->_col = uncle->_col = BLACK;
                    granparent->_col = RED;

                    cur = granparent;
                    parent = cur->_parent;
                }
                else
                {
                    if (cur == parent->_right)
                    {
                        RotateL(granparent);

                        parent->_col = BLACK;
                        granparent->_col = RED;
                    }
                    else
                    {
                        RotateR(parent);
                        RotateL(granparent);

                        cur->_col = BLACK;
                        granparent->_col = RED;
                    }
                    break;
                }
            }
        }

        //确保根节点为黑
        _root->_col = BLACK;
        return make_pair(iterator(newnode), true);
    }

    bool IsRBTree()
    {
        if (_root == nullptr)
        {
            return true;
        }

        if (_root->_col == RED)
        {
            cout << "根节点为红色" << endl;
            return false;
        }

        int Blacknum = 0;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_col == BLACK)
                Blacknum++;
            cur = cur->_left;
        }

        int i = 0;
        return _IsRBTree(_root, Blacknum, i);
    }

private:
    void _Destory(Node*&amp; root)
    {
        if (root == nullptr)
            return;

        _Destory(root->_left);
        _Destory(root->_right);

        delete root;
        root = nullptr;
    }
    
    bool _IsRBTree(Node* root, int blacknum, int count)
    {
        if (root == nullptr)
        {
            if (blacknum == count)
                return true;
            cout << "各路径上黑色节点个数不同" << endl;
            return false;
        }

        if (root->_col == RED &amp;&amp; root->_parent->_col == RED)
        {
            cout << "存在连续红色节点" << endl;
            return false;
        }

        if (root->_col == BLACK)
            count++;

        return _IsRBTree(root->_left, blacknum, count) &amp;&amp; _IsRBTree(root->_right, blacknum, count);
    }

    void RotateL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        Node* parentP = parent->_parent;


        parent->_right = subRL;
        if (subRL)
        {
            subRL->_parent = parent;
        }

        subR->_left = parent;
        parent->_parent = subR;

        if (parent == _root)
        {
            _root = subR;
            subR->_parent = nullptr;
        }
        else
        {
            subR->_parent = parentP;
            if (parentP->_left == parent)
            {
                parentP->_left = subR;
            }
            else
            {
                parentP->_right = subR;
            }
        }
    }

    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        Node* parentP = parent->_parent;


        parent->_left = subLR;
        if (subLR)
        {
            subLR->_parent = parent;
        }

        subL->_right = parent;
        parent->_parent = subL;

        if (parent == _root)
        {
            _root = subL;
            subL->_parent = nullptr;
        }
        else
        {
            subL->_parent = parentP;
            if (parentP->_left == parent)
            {
                parentP->_left = subL;
            }
            else
            {
                parentP->_right = subL;
            }
        }
    }

private:
    Node* _root;
};

二:map的封装和模拟实现

  • 代码:
代码语言:javascript
复制
namespace ymhh
{
    template<class K, class V>
    class map
    {
        struct MapOfKey
        {
            const K&amp; operator()(const pair<K, V>&amp; kv)
            {
                return kv.first;
            }
        };
    public:
        typedef typename RBTree<K, pair<const K, V>, MapOfKey>::iterator iterator;
        typedef typename RBTree<K, pair<const K, V>, MapOfKey>::reverse_iterator reverse_iterator;

        iterator begin()
        {
            return _t.begin();
        }

        iterator end()
        {
            return _t.end();
        }

        reverse_iterator rbegin()
        {
            return _t.rbegin();
        }

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

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

        iterator find(const K&amp; key)
        {
            return _t.Find(key);
        }

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

三: set的封装和模拟实现

  • 代码:
代码语言:javascript
复制
namespace ymhh
{
    template<class K>
    class set
    {
        struct SetOfKey
        {
            const K&amp; operator()(const K&amp; key)
            {
                return key;
            }
        };
    public:
        typedef typename RBTree<K,K, SetOfKey>::iterator iterator;
        typedef typename RBTree<K,K, SetOfKey>::reverse_iterator reverse_iterator;

        iterator begin()
        {
            return _t.begin();
        }

        iterator end()
        {
            return _t.end();
        }

        reverse_iterator rbegin()
        {
            return _t.rbegin();
        }

        reverse_iterator rend()
        {
            return _t.rend();
        }

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

        iterator find(const K&amp; key)
        {
            return _t.Find(key);
        }

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

总结

因为红黑树的增删查改都是O(logN),所以用红黑树实现的map/set的增删查改也是O(logN),是个非常优秀的容器

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-10-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一:红黑树的封装与适配
  • 二:map的封装和模拟实现
  • 三: set的封装和模拟实现
  • 总结
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档