通过红黑树封装 map 和 set 容器

一、红黑树的迭代器

红黑树的遍历默认为中序遍历 —— key 从小到大,因此 begin() 应该获取到红黑树的最左节点 —— 最小,end() 获取到红黑树最右节点的下一个位置, operator++() 也应保证红黑树的遍历为中序的状态。

首先对红黑树节点进行改造:

引入一个模板参数 T ,使 RBTreeNode / RBTree 成为一个可以自动推演类型的容器,当我们向 RBTree 中传 key 时,封装 set 容器;向 RBTree 中传 pair<key, value> 时,封装 map 容器。

1.1 定义红黑树的迭代器:
	template<class T, class Ref, class Ptr> // 与 list 迭代器处没有区别,Ref —— T& ,Ptr —— T*
    struct RBTreeIterator
    {
   
        typedef RBTreeNode<T> Node;
        typedef RBTreeNodeIterator<T, Ref, Ptr> Self;
        Node* _node;
        
        RBTreeIterator(Node* node)
            :_node(node)
        {
   }
    };
1.2 红黑树 operator++()

请务必记住:红黑树迭代器 ++ 为中序遍历 —— 左子树 — 根 — 右子树 !

假设 cur —— 迭代器 已经走到了 key 为 8 的节点 位置,这代表着 key 为 8 的节点 的左子树已经遍历过了key 为 8 的节点 的右子树不为空,则中序遍历 key 为 8 的节点 的右子树

	iterator operator++()
    {
   
        if (_node == nullptr) // 空树,直接返回 空 的迭代器
        {
   
            return iterator(nullptr); 
        }
        
        if (_node->_right)
        {
   
            Node* subLeft = _node->_right;
            while (subLeft->_left)
            {
   
                subLeft = subLeft->_left;
            }
            _node = subLeft;
        }
        
        return *this;
    }

经过 operator++() 后,cur 到了 key 为 11 的节点 位置,此时 cur->_right 为空,表明以 key 为 11 的节点 为最右节点的子树已经全部遍历过,要去找从根到当前节点的简单路径中,cur 所在子树左子树最近祖宗节点

	iterator operator++()
    {
   
        // ...
        if (_node->_right)
        {
    //... }
        else 
        {
   
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur != parent->_left) // parent 存在 且 cur所在子树不是parent的左子树时
            {
   
                cur = parent;
                parent = cur->_parent;
            }
            _node = parent;
        }
        return *this;
    }
总结:
  1. 迭代器指向节点的右子树不为空时, operator++() 的下一个位置就是其右子树的最左节点
  2. 迭代器指向节点的右子树为空,意味当前节点所在的左子树已经全部访问完了,operator++() 的下一个位置是当前子树为左子树的最近祖宗节点
1.3 operator*()
	Ref operator*()
    {
   
        return _node->_data;
    }
1.4 operator->()
	Ptr operator->()
    {
   
        return &(_node->_data);
    }

二、改造红黑树

在对红黑树进行修改之前,首先得明确:

  1. 老版本 Node(RBTreeNode) 的 data 类型是 pair<K, V>,我们通常把 K 当做键值,进而实现节点的查找、map::value 的修改等功能。
  2. 改造 Node 的目的是我们对模板参数 T 传 key 时,则编译器封装出 set 容器;对 T 传 pair<K, V> 时,则封装 map 容器。以此减少冗余代码。

为了避免与 STL 中的 map 和 set 冲突,请在自己定义的命名空间内实现!

2.1 初步改造红黑树
	template<class K, class T>
    class RBTree
    {
   
        typedef RBTreeNode<T> Node;
        typedef RBTreeIterator<T, T&, T*> iterator;
        typedef RBTreeIterator
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值