当前位置: 首页 > article >正文

【C++】25.封装红黑树实现mymap和myset

文章目录

  • 1. 源码及框架分析
  • 2. 模拟实现map和set
    • 2.1 实现出复用红黑树的框架,并支持insert
    • 2.2 支持iterator的实现
      • 2.2.1 iterator核心源代码
      • 2.2.2 iterator实现思路分析
    • 2.3 map支持[]
    • 2.4 bit::map和bit::set代码实现
      • Myset.h
      • Mymap.h
      • RBTree.h


1. 源码及框架分析

SGI-STL30版本源代码,mapset的源代码在map/set/stl_map.h/stl_set.h/stl_tree.h等几个头文件中。

mapset的实现结构框架核心部分截取出来如下:

// set
#ifndef __SGI_STL_INTERNAL_TREE_H
#include <stl_tree.h>
#endif
#include <stl_set.h>
#include <stl_multiset.h>
// map
#ifndef __SGI_STL_INTERNAL_TREE_H
#include <stl_tree.h>
#endif
#include <stl_map.h>
#include <stl_multimap.h>
// stl_set.h
template <class Key, class Compare = less<Key>, class Alloc = alloc>
    class set {
        public:
        // typedefs:
        typedef Key key_type;
        typedef Key value_type;
        private:
        typedef rb_tree<key_type, value_type, 
        identity<value_type>, key_compare, Alloc> rep_type;
        rep_type t; // red-black tree representing set
    };
// stl_map.h
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
    class map {
        public:
        // typedefs:
        typedef Key key_type;
        typedef T mapped_type;
        typedef pair<const Key, T> value_type;
        private:
        typedef rb_tree<key_type, value_type, 
        select1st<value_type>, key_compare, Alloc> rep_type;
        rep_type t; // red-black tree representing map
    };
// stl_tree.h
struct __rb_tree_node_base
{
    typedef __rb_tree_color_type color_type;
    typedef __rb_tree_node_base* base_ptr;
    color_type color; 
    base_ptr parent;
    base_ptr left;
    base_ptr right;
};
// stl_tree.h
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc 
    = alloc>
    class rb_tree {
        protected:
        typedef void* void_pointer;
        typedef __rb_tree_node_base* base_ptr;
        typedef __rb_tree_node<Value> rb_tree_node;
        typedef rb_tree_node* link_type;
        typedef Key key_type;
        typedef Value value_type;
        public:
        // insert用的是第二个模板参数左形参
        pair<iterator,bool> insert_unique(const value_type& x);

        // erase和find用第一个模板参数做形参
        size_type erase(const key_type& x);
        iterator find(const key_type& x);
        protected:
        size_type node_count; // keeps track of size of tree
        link_type header;
    };
template <class Value>
    struct __rb_tree_node : public __rb_tree_node_base
    {
        typedef __rb_tree_node<Value>* link_type;
        Value value_field;
    };
  • 通过下图对框架的分析,我们可以看到源码中rb_tree用了一个巧妙的泛型思想实现,rb_tree是实现key的搜索场景,不是key/value的搜索场景不是直接写死的,而是由第二个模板参数Value决定_rb_tree_node中存储的数据类型。
  • set实例化rb_tree时第二个模板参数给的是keymap实例化rb_tree时第二个模板参数给的是pair<const key, T>,这样一颗红黑树既可以实现key搜索场景的set,也可以实现key/value搜索场景的map
  • 要注意一下,源码里面模板参数是用T代表value,而内部写的value_type不是我们我们日常key/value场景中说的value,源码中的value_type反而是红黑树结点中存储的真实的数据的类型。
  • rb_tree第二个模板参数Value已经控制了红黑树结点中存储的数据类型,为什么还要传第一个模板参数Key呢?尤其是set,两个模板参数是一样的,这是很多人的一个疑问。要注意的是对于mapsetfind/erase时的函数参数都是Key,所以第一个模板参数是传给find/erase等函数做形参的类型的。对于set而言两个参数是一样的,但是对于map而言就完全不一样了,map insert的是pair对象,但是findease的是Key对象。
  • 吐槽一下,这里源码命名风格比较乱,set模板参数用的Key命名,map用的是KeyT命名,而rb_tree用的又是KeyValue,可见大佬有时写代码也不规范,乱弹琴。

02eac34d6b01ed56fc3d499f832832bc


2. 模拟实现map和set

2.1 实现出复用红黑树的框架,并支持insert

参考源码框架,mapset复用之前我们实现的红黑树。

我们这里相比源码调整一下,key参数就用Kvalue参数就用V,红黑树中的数据类型,我们使用T。

其次因为RBTree实现了泛型不知道T参数导致是K,还是pair<K, V>,那么insert内部进行插入逻辑比较时,就没办法进行比较,因为pair的默认支持的是keyvalue一起参与比较,我们需要时的任何时候只比较key,所以我们在mapset层分别实现一个MapKeyOfTSetKeyOfT的仿函数传给RBTreeKeyOfT,然后RBTree中通过KeyOfT仿函数取出T类型对象中的key,再进行比较,具体细节参考如下代码实现。

// pair的<运算符重载,用于比较两个pair对象
template <class T1, class T2>
bool operator< (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ 
    // 先比较first,如果first相等再比较second
    // 返回true的两种情况:
    // 1. lhs.first小于rhs.first
    // 2. first相等(!(rhs.first<lhs.first))且lhs.second小于rhs.second
    return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second); 
}

namespace bit
{
    // map类模板:实现键值对的映射
    template<class K, class V>
    class map
    {
        // MapKeyOfT仿函数类,用于从pair中提取key
        struct MapKeyOfT
        {
            // 重载()运算符,返回pair中的first作为键值
            const K& operator()(const pair<K, V>& kv)
            {
                return kv.first;
            }
        };

        public:
        // 插入键值对
        bool insert(const pair<K, V>& kv)
        {
            return _t.Insert(kv);
        }

        private:
        // 底层使用红黑树存储,K是键类型,pair<K,V>是实际存储的数据类型,MapKeyOfT用于提取键
        RBTree<K, pair<K, V>, MapKeyOfT> _t;
    };

    // set类模板:实现集合
    template<class K>
    class set
    {
        // SetKeyOfT仿函数类,用于返回键值本身
        struct SetKeyOfT
        {
            // 由于set中key就是value,直接返回key
            const K& operator()(const K& key)
            {
                return key;
            }
        };

        public:
        // 插入元素
        bool insert(const K& key)
        {
            return _t.Insert(key);
        }

        private:
        // 底层使用红黑树存储,K既是键类型也是数据类型
        RBTree<K, K, SetKeyOfT> _t;
    };
}

// 定义红黑树节点的颜色
enum Colour
{
    RED,    // 红色节点
    BLACK   // 黑色节点
};

// 红黑树节点结构
template<class T>
struct RBTreeNode
{
    T _data;                  // 节点数据
    RBTreeNode<T>* _left;     // 左子节点
    RBTreeNode<T>* _right;    // 右子节点
    RBTreeNode<T>* _parent;   // 父节点
    Colour _col;              // 节点颜色

    // 节点构造函数
    RBTreeNode(const T& data)
        : _data(data)
        , _left(nullptr)
        , _right(nullptr)
        , _parent(nullptr)
    {}
};

// 红黑树类模板
// K: 键类型
// T: 数据类型
// KeyOfT: 从数据中提取键的仿函数类型
template<class K, class T, class KeyOfT>
class RBTree
{
    private:
    typedef RBTreeNode<T> Node;    // 节点类型别名
    Node* _root = nullptr;         // 根节点指针

    public:
    // 插入数据
    bool Insert(const T& data)
    {
        // 空树情况处理
        if (_root == nullptr)
        {
            _root = new Node(data);
            _root->_col = BLACK;    // 根节点必须为黑色
            return true;
        }

        KeyOfT kot;                // 创建KeyOfT对象用于提取键值
        Node* parent = nullptr;     // 记录父节点
        Node* cur = _root;         // 从根节点开始查找

        // 查找插入位置
        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 false;   // 键值已存在,插入失败
            }
        }

        // 创建新节点
        cur = new Node(data);
        Node* newnode = cur;
        cur->_col = RED;       // 新节点默认为红色

        // 连接新节点到父节点
        if (kot(parent->_data) < kot(data))
        {
            parent->_right = cur;   // 作为右子节点
        }
        else
        {
            parent->_left = cur;    // 作为左子节点
        }
        cur->_parent = parent;      // 设置父节点

        // 这里省略了红黑树的平衡调整代码
        return true;
    }
};

2.2 支持iterator的实现

2.2.1 iterator核心源代码

// 红黑树基础迭代器结构
struct __rb_tree_base_iterator
{
    // 定义节点指针类型别名
    typedef __rb_tree_node_base::base_ptr base_ptr;
    base_ptr node;  // 当前节点指针

    // 迭代器自增操作
    void increment()
    {
        if (node->right != 0) {  // 如果有右子树
            node = node->right;   // 先往右走一步
            while (node->left != 0)  // 然后一直往左走到底
                node = node->left;    // 找到右子树中的最小值
        }
        else {  // 如果没有右子树
            base_ptr y = node->parent;  // 获取父节点
            // 如果当前节点是父节点的右子节点,就继续往上找
            while (node == y->right) {
                node = y;
                y = y->parent;
            }
            // 特殊情况处理:如果当前节点不是其右子节点
            if (node->right != y)
                node = y;
        }
    }

    // 迭代器自减操作
    void decrement()
    {
        // 特殊情况:如果是红节点且父节点的父节点是自己
        // 说明这是一个header节点
        if (node->color == __rb_tree_red &&
            node->parent->parent == node)
            node = node->right;  // 转到最大节点
        else if (node->left != 0) {  // 如果有左子树
            base_ptr y = node->left;  // 转到左子树
            while (y->right != 0)     // 然后一直往右走到底
                y = y->right;         // 找到左子树中的最大值
            node = y;
        }
        else {  // 如果没有左子树
            base_ptr y = node->parent;  // 获取父节点
            // 如果当前节点是父节点的左子节点,就继续往上找
            while (node == y->left) {
                node = y;
                y = y->parent;
            }
            node = y;  // 找到第一个不是左子节点的祖先
        }
    }
};

// 红黑树迭代器模板类,继承自基础迭代器
template <class Value, class Ref, class Ptr>
struct __rb_tree_iterator : public __rb_tree_base_iterator
{
    typedef Value value_type;    // 值类型
    typedef Ref reference;       // 引用类型
    typedef Ptr pointer;         // 指针类型
    
    // 定义迭代器类型
    typedef __rb_tree_iterator<Value, Value&, Value*> iterator;
    
    // 构造函数
    __rb_tree_iterator() {}  // 默认构造
    __rb_tree_iterator(link_type x) { node = x; }  // 节点指针构造
    __rb_tree_iterator(const iterator& it) { node = it.node; }  // 拷贝构造

    // 重载解引用操作符
    reference operator*() const { return link_type(node)->value_field; }

    // 重载箭头操作符(如果支持的话)
#ifndef __SGI_STL_NO_ARROW_OPERATOR
    pointer operator->() const { return &(operator*()); }
#endif

    // 重载前置自增/自减操作符
    self& operator++() { increment(); return *this; }
    self& operator--() { decrement(); return *this; }
};

// 重载相等操作符
inline bool operator==(const __rb_tree_base_iterator& x,
                      const __rb_tree_base_iterator& y) {
    return x.node == y.node;
}

// 重载不等操作符
inline bool operator!=(const __rb_tree_base_iterator& x,
                      const __rb_tree_base_iterator& y) {
    return x.node != y.node;
}

2.2.2 iterator实现思路分析

iterator实现的大框架跟list的iterator思路是一致的,用一个类型封装结点的指针,再通过重载运算符实现,迭代器像指针一样访问的行为。

这里的难点是operator++和operator–的实现。之前使用部分,我们分析了,map和set的迭代器走的是中序遍历,左子树->根结点->右子树,那么begin()会返回中序第一个结点的iterator也就是10所在结点的迭代器。

迭代器++的核心逻辑就是不看全局,只看局部,只考虑当前中序局部要访问的下一个结点。

迭代器++时,如果it指向的结点的右子树不为空,代表当前结点已经访问完了,要访问下一个结点是右子树的中序第一个,一棵树中序第一个是最左结点,所以直接找右子树的最左结点即可。

迭代器++时,如果it指向的结点的右子树空,代表当前结点已经访问完了且当前结点所在的子树也访问完了,要访问的下一个结点在当前结点的祖先里面,所以要沿着当前结点到根的祖先路径向上找。

如果当前结点是父亲的左,根据中序左子树->根结点->右子树,那么下一个访问的结点就是当前结点的父亲;如下图:it指向25,25右为空,25是30的左,所以下一个访问的结点就是30。

如果当前结点是父亲的右,根据中序左子树->根结点->右子树,当前当前结点所在的子树访问完了,当前结点所在父亲的子树也访问完了,那么下一个访问的需要继续往根的祖先中去找,直到找到孩子是父亲左的那个祖先就是中序要问题的下一个结点。如下图:it指向15,15右为空,15是10的右,15所在子树话访问完了,10所在子树也访问完了,继续往上找,10是18的左,那么下一个访问的结点就是18。

end()如何表示呢?如下图:当it指向50时,++it时,50是40的右,40是30的右,30是18的右,18到根没有父亲,没有找到孩子是父亲左的那个祖先,这是父亲为空了,那我们就把it中的结点指针置为nullptr,我们用nullptr去充当end。需要注意的是stl源码空,红黑树增加了一个哨兵位头结点做为end(),这哨兵位头结点和根互为父亲,左指向最左结点,右指向最右结点。相比我们用nullptr作为end(),差别不大,他能实现的,我们也能实现。只是–end()判断到结点时空,特殊处理一下,让迭代器结点指向最右结点。具体参考迭代器–实现。

迭代器–的实现跟++的思路完全类似,逻辑正好反过来即可,因为他访问顺序是右子树->根结点->左子树,具体参考下面代码实现。

set的iterator也不支持修改,我们把set的第二个模板参数改成const K即可, RBTree<K, const K, SetKeyOfT> _t;

map的iterator不支持修改key但是可以修改value,我们把map的第二个模板参数pair的第一个参数改成const K即可, RBTree<K, pair<const K, V>, MapKeyOfT> _t;

支持完整的迭代器还有很多细节需要修改,具体参考下面题的代码。


2.3 map支持[]

  • map要支持[]主要需要修改insert返回值支持,修改RBtree中的insert返回值为pair<Iterator, bool> Insert(const T& data)
  • 有了insert支持[]实现就很简单了,具体参考下面代码实现

2.4 bit::map和bit::set代码实现

Myset.h

#include"RBTree.h"

namespace bit {
    template<class K>
    class set {
        // 仿函数类:用于set中获取键值
        // 因为set中key就是value,所以直接返回key即可
        struct SetKeyOfT {
            const K& operator()(const K& key) {
                return key;
            }
        };

    public:
        // 使用RBTree的迭代器类型
        typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;
        typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator const_iterator;

        // 迭代器相关函数
        iterator begin() {
            return _t.Begin();
        }
        iterator end() {
            return _t.End();
        }
        // const对象使用的迭代器接口
        const_iterator begin() const {
            return _t.Begin();
        }
        const_iterator end() const {
            return _t.End();
        }

        // 插入函数:返回pair,包含迭代器和是否插入成功
        pair<iterator, bool> insert(const K& key) {
            return _t.Insert(key);
        }

        // 查找函数:返回指向目标位置的迭代器
        iterator find(const K& key) {
            return _t.Find(key);
        }

    private:
        // 底层红黑树对象
        RBTree<K, const K, SetKeyOfT> _t;
    };

    // 用于打印set内容的辅助函数
    void Print(const set<int>& s) {
        set<int>::const_iterator it = s.end();
        while (it != s.begin()) {
            --it;
            // 注意:不支持修改值
            //*it += 2;
            cout << *it << " ";
        }
        cout << endl;
    }

    // set测试函数
    void test_set() {
        set<int> s;
        int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
        // 插入数组中的所有元素
        for (auto e : a) {
            s.insert(e);
        }
        // 正向遍历打印
        for (auto e : s) {
            cout << e << " ";
        }
        cout << endl;

        Print(s);  // 反向打印
    }
}

Mymap.h

#include"RBTree.h"
namespace bit {
    template<class K, class V>
    class map {
        // 仿函数类:从pair中获取key
        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>::ConstIterator 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();
        }

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

        // 查找操作
        iterator find(const K& key) {
            return _t.Find(key);
        }

        // []运算符重载:支持通过key访问/插入value
        V& operator[](const K& key) {
            // 如果key不存在,插入pair(key, V())
            // 如果key存在,返回对应的value引用
            pair<iterator, bool> ret = insert(make_pair(key, V()));
            return ret.first->second;
        }

    private:
        // 底层红黑树对象
        RBTree<K, pair<const K, V>, MapKeyOfT> _t;
    };

    // map测试函数
    void test_map() {
        map<string, string> dict;
        // 测试insert
        dict.insert({ "sort", "排序" });
        dict.insert({ "left", "左边" });
        dict.insert({ "right", "右边" });

        // 测试[]操作符
        dict["left"] = "左边,剩余";
        dict["insert"] = "插入";
        dict["string"];  // 插入默认值

        // 遍历打印
        map<string, string>::iterator it = dict.begin();
        while (it != dict.end()) {
            // 注意:不能修改first,可以修改second
            //it->first += 'x';  // 错误
            it->second += 'x';   // 正确
            cout << it->first << ":" << it->second << endl;
            ++it;
        }
        cout << endl;
    }
}

RBTree.h

// 定义红黑树节点的颜色
enum Colour {
    RED,
    BLACK
};

// 红黑树节点结构
template<class T>
struct RBTreeNode {
    T _data;                    // 节点数据
    RBTreeNode<T>* _left;       // 左子节点
    RBTreeNode<T>* _right;      // 右子节点
    RBTreeNode<T>* _parent;     // 父节点
    Colour _col;                // 节点颜色

    // 节点构造函数
    RBTreeNode(const T& data)
        : _data(data)
        , _left(nullptr)
        , _right(nullptr)
        , _parent(nullptr)
    {}
};

// 红黑树的迭代器
template<class T, class Ref, class Ptr>
struct RBTreeIterator {
    typedef RBTreeNode<T> Node;
    typedef RBTreeIterator<T, Ref, Ptr> Self;

    Node* _node;    // 当前节点指针
    Node* _root;    // 根节点指针

    // 构造函数
    RBTreeIterator(Node* node, Node* root)
        :_node(node)
        ,_root(root)
    {}

    // 前置++:中序遍历的下一个节点
    Self& operator++() {
        if (_node->_right) {
            // 如果有右子树,找右子树的最左节点
            Node* leftMost = _node->_right;
            while (leftMost->_left) {
                leftMost = leftMost->_left;
            }
            _node = leftMost;
        }
        else {
            // 如果没有右子树,向上找第一个作为左子树的祖先
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_right) {
                cur = parent;
                parent = cur->_parent;
            }
            _node = parent;
        }
        return *this;
    }

    // 前置--:中序遍历的前一个节点
    Self& operator--() {
        if (_node == nullptr) {  // 处理end()迭代器
            // 找整棵树的最右节点
            Node* rightMost = _root;
            while (rightMost && rightMost->_right) {
                rightMost = rightMost->_right;
            }
            _node = rightMost;
        }
        else if (_node->_left) {
            // 有左子树,找左子树的最右节点
            Node* rightMost = _node->_left;
            while (rightMost->_right) {
                rightMost = rightMost->_right;
            }
            _node = rightMost;
        }
        else {
            // 没有左子树,向上找第一个作为右子树的祖先
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_left) {
                cur = parent;
                parent = cur->_parent;
            }
            _node = parent;
        }
        return *this;
    }

    // 解引用操作
    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;
    }
};

// 红黑树类模板
template<class K, class T, class KeyOfT>
class RBTree {
    typedef RBTreeNode<T> Node;
public:
    typedef RBTreeIterator<T, T&, T*> Iterator;
    typedef RBTreeIterator<T, const T&, const T*> ConstIterator;

    // 获取树的起始迭代器
    Iterator Begin() {
        Node* leftMost = _root;
        while (leftMost && leftMost->_left) {
            leftMost = leftMost->_left;
        }
        return Iterator(leftMost, _root);
    }

    // 获取树的结束迭代器
    Iterator End() {
        return Iterator(nullptr, _root);
    }

    // const版本的迭代器接口
    ConstIterator Begin() const {
        Node* leftMost = _root;
        while (leftMost && leftMost->_left) {
            leftMost = leftMost->_left;
        }
        return ConstIterator(leftMost, _root);
    }
    ConstIterator End() const {
        return ConstIterator(nullptr, _root);
    }

    // 默认构造函数
    RBTree() = default;

    // 析构函数
    ~RBTree() {
        Destroy(_root);
        _root = nullptr;
    }

    // 插入函数
    pair<Iterator, bool> Insert(const T& data) {
        // 空树情况处理
        if (_root == nullptr) {
            _root = new Node(data);
            _root->_col = BLACK;  // 根节点必须是黑色
            return make_pair(Iterator(_root, _root), true);
        }

        KeyOfT kot;
        Node* parent = nullptr;
        Node* cur = _root;

        // 查找插入位置
        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, _root), false);
            }
        }

        // 创建新节点
        cur = new Node(data);
        Node* newnode = cur;
        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;
                // 情况1:uncle存在且为红
                if (uncle && uncle->_col == RED) {
                    parent->_col = uncle->_col = BLACK;
                    grandfather->_col = RED;
                    cur = grandfather;
                    parent = cur->_parent;
                }
                else {  // 情况2/3:uncle不存在或为黑
                    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;
                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);
                        parent->_col = BLACK;
                        grandfather->_col = RED;
                    }
                    else {
                        RotateR(parent);
                        RotateL(grandfather);
                        cur->_col = BLACK;
                        grandfather->_col = RED;
                    }
                    break;
                }
            }
        }

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

    // 查找函数
    Iterator Find(const K& key) {
        Node* cur = _root;
        while (cur) {
            if (cur->_kv.first < key) {
                cur = cur->_right;
            }
            else if (cur->_kv.first > key) {
                cur = cur->_left;
            }
            else {
                return Iterator(cur, _root);
            }
        }
        return End();
    }

private:
    // 左旋操作
    void RotateL(Node* parent) {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;

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

        Node* parentParent = parent->_parent;

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

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

    // 右旋操作
    void RotateR(Node* parent) {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;

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

        Node* parentParent = parent->_parent;

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

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

    // 销毁树
    void Destroy(Node* root) {
        if (root == nullptr)
            return;
        Destroy(root->_left);
        Destroy(root->_right);
        delete root;
    }

private:
    Node* _root = nullptr;  // 根节点指针
};

http://www.kler.cn/a/543179.html

相关文章:

  • 云服务器流量包用尽(中病毒)
  • DeepScaleR:仅用 1.5B 参数超越 OpenAI O1-Preview 的强化学习模型
  • 正则表达式(竞赛篇)
  • 集成学习(一):从理论到实战(附代码)
  • Linux系统安装Nginx详解(适用于CentOS 7)
  • 一个基于ESP32S3和INMP441麦克风实现音频强度控制RGB灯带律动的代码及效果展示
  • ANR学习
  • 20250212:sigmastar系列1-获取UUID
  • Web项目测试专题(六)压力测试
  • IDEA中打包maven项目,提示Compilation failure
  • 政安晨的AI大模型训练实践 六 - open-webui vLLM 运行
  • python自动化测试之Pytest断言及Allure报告定制
  • 跟着李沐老师学习深度学习(七)
  • 三角测量——用相机运动估计特征点的空间位置
  • JavaSE基本知识补充 -Map集合
  • DeepSeek与核货宝订货系统的协同进化:智能商业范式重构
  • AI大模型介绍yolo
  • P5:使用pytorch实现运动鞋识别
  • 碰一碰发视频源码技术开发,支持OEM
  • 蓝桥杯 Java B 组之排序算法(冒泡、选择、插入排序)
  • 如何在VSCode中免费使用DeepSeek R1:本地大模型编程助手全攻略
  • Visual Studio 使用 “Ctrl + /”键设置注释和取消注释
  • 【问】强学如何支持 迁移学习呢?
  • 使用Python爬虫获取淘宝Custom API接口数据
  • 极坐标 径向位置
  • DataBase【MySQL基础夯实使用说明(中)】