【C++学习手札】基于红黑树封装模拟实现map和set

简介: 【C++学习手札】基于红黑树封装模拟实现map和set

一、前言

 本文主要叙述基于红黑树对于map和set的封装实现,需要有红黑树的知识前提。由于前面作者对于红黑树主要只是模拟实现了插入的功能。因此本文也只是实现map和set相应的功能,本文的主要要点在于map和set的封装以及迭代器中++和--的实现

map和set的底层原理

C++中的map和set都是STL中的关联容器,都基于红黑树实现。其中set是K模型的容器而map是KV模型的容器,本文主要讲述用一棵KV模型的红黑树同时实现map和set。map和set都使用红黑树的基本操作,时间复杂度为O(log n),其中n为元素数量。因此,map和set都是高效的关联容器。


二、红黑树的封装

通过模板使得map和set都可复用红黑树

  可以看到我们定义了一个模板参数T,通过T的类型变化来改变红黑树中每一个节点的值,从而控制整颗红黑树的复用。

enum Colour
{
  RED,
  BLACK
};
template<class T>
struct RBTreeNode
{
  RBTreeNode<T>* _left;
  RBTreeNode<T>* _right;
  RBTreeNode<T>* _parent;
  T _data;
  Colour _col;
  RBTreeNode(const T& data)
    :_left(nullptr)
    , _right(nullptr)
    , _parent(nullptr)
    , _data(data)
    , _col(RED)
  {}
};

迭代器类

迭代器实际上是对于指针进行操作,因此我们实例化并且重新命名了节点类的指针Node,由于迭代器分为是否常量迭代器,对此我们额外定义了两个模板参数Ref、Ptr用于控制其中重载运算符 T& operator*() 和 T* operator->()当我们实例化时,区分Ref是const T&还是T&、Ptr是const T*还是T*后面RBTree中会有所体现。在迭代器中,其中,operator*和operator->返回指向节点的指针,operator++和operator--实现前后缀++/--运算符,operator==和operator!=用来比较两个迭代器是否指向同一个节点。

以下为大致实现的功能
template<class T, class Ref, class Ptr>
struct __TreeIterator
{
  typedef RBTreeNode<T> Node;
  typedef __TreeIterator<T, Ref, Ptr> Self;
  Node* _node;
  __TreeIterator(Node* node)
    :_node(node)
  {}
  Self& operator--();
  Self& operator++();
  Ref operator*()
  {
    return _node->_data;
  }
  Ptr operator->()
  {
    return &_node->_data;
  }
  bool operator!=(const Self& s)
  {
    return _node != s._node;
  }
  bool operator==(const Self& s)
  {
    return _node == s._node;
  }
};
operator++()

对于map和set的遍历我们默认都是中序遍历,也就是左子树 根 右子树。因此对于++操作我们首要的是找到下一个节点,则这个下一个节点便是在这个节点的右子树,也就是而下一个节点的准确位置为:这个节点的右子树的最左节点(为什么呢?因为左 根 右我们将这个节点看作为根,则下一个节点位置为右子树,而右子树的第一个节点则为最左的节点)。 当这个节点的右为空,意味着包括这个节点在内的左 根 右都遍历完了,那么我们就需要向上遍历。则需遵循以下:如果孩子是父亲的左就返回父亲(这就是意味着遍历完了左 接下来要遍历 根),否则就继续向上遍历,如果走到nullptr那就是遍历完成。

总结一下遍历规则

1、如果_node的右不为空,找右孩子的最左节点

2、如果_node的右为空,如果孩子是父亲的左就返回父亲,否则就继续向上遍历,如果走到nullptr那就是遍历完成

  Self& operator++()
  {
    if (_node->_right)
    {
      // 下一个就是右子树的最左节点
      Node* cur = _node->_right;
      while (cur->_left)
      {
        cur = cur->_left;
      }
      _node = cur;
    }
    else
    {
      // 左子树 根 右子树
      // 右为空,找孩子是父亲左的那个祖先
      Node* cur = _node;
      Node* parent = cur->_parent;
      while (parent && cur == parent->_right)
      {
        cur = parent;
        parent = parent->_parent;
      }
      _node = parent;
    }
    return *this;
  }
operator--()

和上面的operator++()相似,但是我们的遍历顺序变为了右子树 根 左子树。

总结一下遍历规则:

1、如果_node的左不为空,找左孩子的最右节点

2、如果_node的左为空,如果孩子是父亲的右就返回父亲,否则就继续向上遍历,如果走到nullptr那就是遍历完成

  Self& operator--()
  {
    if (_node->_left)
    {
      Node* cur = _node->_left;
      while (cur->_right)
      {
        cur = cur->_right;
      }
      _node = cur;
    }
    else
    {
      Node* cur = _node;
      Node* parent = cur->_parent;
      while (parent && cur == parent->_left)
      {
        cur = parent;
        parent = parent->_parent;
      }
      _node = parent;
    }
    return *this;
  }

红黑树类

从之前我们所学习的红黑树的模拟实现我们可以知道,红黑树的插入等等操作中会用到对于key的比较。对此,set和map的比较要求是不同的,set可以直接用key进行比较,而map中对于pair的比较是先按first比较再比价second,而我们想要的结果是只比较first,因此我们定义了个KeyofT来对map和set进行区分。这个KeyofT则是通过传递仿函数来进行控制对于要比较值的转换。

// set->RBTree<K, K, SetKeyOfT> _t;
// map->RBTree<K, pair<const K, T>, MapKeyOfT> _t;
template<class K, class T, class KeyOfT>
class RBTree
{
  typedef RBTreeNode<T> Node;
public:
  typedef __TreeIterator<T, T&, T*> iterator;
  typedef __TreeIterator<T, const T&, const T*> const_iterator;
  iterator begin();
  iterator end();
  const_iterator begin();
  const_iterator end();
  //pair<iterator, bool> Insert(const T& data)
  pair<Node*, bool> Insert(const T& data);
  Node * Find(const K & key)
private:
  Node* _root = nullptr;
};

仿函数

 注意:这里的仿函数是在map和set中定义的,我们在map和set中的迭代器实际上是就是间接的控制了RBTree的迭代器。

map
    struct MapKeyOfT
    {
      const K& operator()(const pair<K, V>& kv)
      {
        return kv.first;
      }
    };
set
    struct SetKeyOfT
    {
      const K& operator()(const K& key)
      {
        return key;
      }
    };

 封装后的红黑树

begin()和end()

STL明确规定,begin()与end()代表的是一段前闭后开的区间,而对红黑树进行中序遍历后,可以得到一个有序的序列,因此:begin()可以放在红黑树中最小节点(即最左侧节点)的位置,end()放在最大节点(最右侧节点)的下一个位置,关键是最大节点的下一个位置在哪块?能否给成nullptr呢?答案是行不通的,因为对end()位置的迭代器进行--操作,必须要能找最后一个元素,此处就不行,因此最好的方式是将end()放在头结点的位置:


虽然但是,作者还是将end()给了nullptr,事实上勉强还是可以用的哈哈哈...


  iterator begin()
  {
    Node* cur = _root;
    while (cur && cur->_left)
    {
      cur = cur->_left;
    }
    return iterator(cur);
  }
  iterator end()
  {
    return iterator(nullptr);
  }
  const_iterator begin() const
  {
    Node* cur = _root;
    while (cur && cur->_left)
    {
      cur = cur->_left;
    }
    return const_iterator(cur);
  }
  const_iterator end() const
  {
    return const_iterator(nullptr);
  }
通过仿函数来控制要比较的值

 注意:这里对于insert以及find中都定义了一个KeyOfT kot; 这个就是上面所提到的用于转化用于比较的数据的仿函数的定义。


其中对于insert有点需要注意:我们运用了pair中的特性,用pair<Node*, bool>接收了make_pair(newnode, true)的返回值,用pair构造了一个新的pair而不是拷贝构造了一个pair后续会提到为什么(在set封装中)

  //pair<iterator, bool> Insert(const T& data)
  pair<Node*, bool> Insert(const T& data)
  {
    if (_root == nullptr)
    {
      _root = new Node(data);
      _root->_col = BLACK;
      return make_pair(_root, true);
    }
    Node* parent = nullptr;
    Node* cur = _root;
    KeyOfT kot;
    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(cur, false);
      }
    }
    // 新增节点给红色
    cur = new Node(data);
    Node* newnode = cur;
    cur->_col = RED;
    if (kot(parent->_data) < kot(data))
    {
      parent->_right = cur;
      cur->_parent = parent;
    }
    else
    {
      parent->_left = cur;
      cur->_parent = parent;
    }
    while (parent && parent->_col == RED)
    {
      Node* grandfather = parent->_parent;
      if (parent == grandfather->_left)
      {
        //     g
        //   p   u
        // c
        Node* uncle = grandfather->_right;
        if (uncle && uncle->_col == RED)
        {
          // 变色
          parent->_col = uncle->_col = BLACK;
          grandfather->_col = RED;
          // 继续往上更新处理
          cur = grandfather;
          parent = cur->_parent;
        }
        else
        {
          if (cur == parent->_left)
          {
            // 单旋
            //     g
            //   p
            // c
            RotateR(grandfather);
            parent->_col = BLACK;
            grandfather->_col = RED;
          }
          else
          {
            // 双旋
            //     g
            //   p
            //     c
            RotateL(parent);
            RotateR(grandfather);
            cur->_col = BLACK;
            grandfather->_col = RED;
          }
          break;
        }
      }
      else  // parent == grandfather->_right
      {
        //     g
        //   u   p 
        //          c
        //
        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
          {
            //     g
            //   u   p 
            //     c
            //
            RotateR(parent);
            RotateL(grandfather);
            cur->_col = BLACK;
            grandfather->_col = RED;
          }
          break;
        }
      }
    }
    _root->_col = BLACK;
    return make_pair(newnode, true);
  }
    Node * Find(const K & key)
  {
    Node* cur = _root;
    KeyOfT kot;
    while (cur!= nullptr)
    { 
      if (kot(cur->_data) < key)
      {
        cur = cur->_left;
      }
      else if (kot(cur->_data) > key)
      {
        cur = cur->_right;
      }
      else
      {
        return cur;
      }
    }
    return nullptr;
  }
完整封装
// set->RBTree<K, K, SetKeyOfT> _t;
// map->RBTree<K, pair<const K, T>, MapKeyOfT> _t;
template<class K, class T, class KeyOfT>
class RBTree
{
  typedef RBTreeNode<T> Node;
public:
  typedef __TreeIterator<T, T&, T*> iterator;
  typedef __TreeIterator<T, const T&, const T*> const_iterator;
  iterator begin()
  {
    Node* cur = _root;
    while (cur && cur->_left)
    {
      cur = cur->_left;
    }
    return iterator(cur);
  }
  iterator end()
  {
    return iterator(nullptr);
  }
  const_iterator begin() const
  {
    Node* cur = _root;
    while (cur && cur->_left)
    {
      cur = cur->_left;
    }
    return const_iterator(cur);
  }
  const_iterator end() const
  {
    return const_iterator(nullptr);
  }
  //pair<iterator, bool> Insert(const T& data)
  pair<Node*, bool> Insert(const T& data)
  {
    if (_root == nullptr)
    {
      _root = new Node(data);
      _root->_col = BLACK;
      return make_pair(_root, true);
    }
    Node* parent = nullptr;
    Node* cur = _root;
    KeyOfT kot;
    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(cur, false);
      }
    }
    // 新增节点给红色
    cur = new Node(data);
    Node* newnode = cur;
    cur->_col = RED;
    if (kot(parent->_data) < kot(data))
    {
      parent->_right = cur;
      cur->_parent = parent;
    }
    else
    {
      parent->_left = cur;
      cur->_parent = parent;
    }
    while (parent && parent->_col == RED)
    {
      Node* grandfather = parent->_parent;
      if (parent == grandfather->_left)
      {
        //     g
        //   p   u
        // c
        Node* uncle = grandfather->_right;
        if (uncle && uncle->_col == RED)
        {
          // 变色
          parent->_col = uncle->_col = BLACK;
          grandfather->_col = RED;
          // 继续往上更新处理
          cur = grandfather;
          parent = cur->_parent;
        }
        else
        {
          if (cur == parent->_left)
          {
            // 单旋
            //     g
            //   p
            // c
            RotateR(grandfather);
            parent->_col = BLACK;
            grandfather->_col = RED;
          }
          else
          {
            // 双旋
            //     g
            //   p
            //     c
            RotateL(parent);
            RotateR(grandfather);
            cur->_col = BLACK;
            grandfather->_col = RED;
          }
          break;
        }
      }
      else  // parent == grandfather->_right
      {
        //     g
        //   u   p 
        //          c
        //
        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
          {
            //     g
            //   u   p 
            //     c
            //
            RotateR(parent);
            RotateL(grandfather);
            cur->_col = BLACK;
            grandfather->_col = RED;
          }
          break;
        }
      }
    }
    _root->_col = BLACK;
    return make_pair(newnode, true);
  }
  void RotateL(Node* parent)
  {
    Node* subR = parent->_right;
    Node* subRL = subR->_left;
    parent->_right = subRL;
    subR->_left = parent;
    Node* parentParent = parent->_parent;
    parent->_parent = subR;
    if (subRL)
      subRL->_parent = parent;
    if (_root == parent)
    {
      _root = subR;
      subR->_parent = nullptr;
    }
    else
    {
      if (parentParent->_left == parent)
      {
        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 (_root == parent)
    {
      _root = subL;
      subL->_parent = nullptr;
    }
    else
    {
      if (parentParent->_left == parent)
      {
        parentParent->_left = subL;
      }
      else
      {
        parentParent->_right = subL;
      }
      subL->_parent = parentParent;
    }
  }
  void InOrder()
  {
    _InOrder(_root);
    cout << endl;
  }
  void _InOrder(Node* root)
  {
    if (root == nullptr)
      return;
    _InOrder(root->_left);
    cout << root->_kv.first << " ";
    _InOrder(root->_right);
  }
  // 根节点->当前节点这条路径的黑色节点的数量
  bool Check(Node* root, int blacknum, const int refVal)
  {
    if (root == nullptr)
    {
      //cout << balcknum << endl;
      if (blacknum != refVal)
      {
        cout << "存在黑色节点数量不相等的路径" << endl;
        return false;
      }
      return true;
    }
    if (root->_col == RED && root->_parent->_col == RED)
    {
      cout << "有连续的红色节点" << endl;
      return false;
    }
    if (root->_col == BLACK)
    {
      ++blacknum;
    }
    return Check(root->_left, blacknum, refVal)
      && Check(root->_right, blacknum, refVal);
  }
  bool IsBalance()
  {
    if (_root == nullptr)
      return true;
    if (_root->_col == RED)
      return false;
    //参考值
    int refVal = 0;
    Node* cur = _root;
    while (cur)
    {
      if (cur->_col == BLACK)
      {
        ++refVal;
      }
      cur = cur->_left;
    }
    int blacknum = 0;
    return Check(_root, blacknum, refVal);
  }
  int Height()
  {
    return _Height(_root);
  }
  int _Height(Node* root)
  {
    if (root == nullptr)
      return 0;
    int leftHeight = _Height(root->_left);
    int rightHeight = _Height(root->_right);
    return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
  }
  size_t Size()
  {
    return _Size(_root);
  }
  size_t _Size(Node* root)
  {
    if (root == NULL)
      return 0;
    return _Size(root->_left)
      + _Size(root->_right) + 1;
  }
  Node * Find(const K & key)
  {
    Node* cur = _root;
    KeyOfT kot;
    while (cur!= nullptr)
    { 
      if (kot(cur->_data) < key)
      {
        cur = cur->_left;
      }
      else if (kot(cur->_data) > key)
      {
        cur = cur->_right;
      }
      else
      {
        return cur;
      }
    }
    return nullptr;
  }
private:
  Node* _root = nullptr;
};

三、map和set的封装

封装后的set

#pragma once
#include"RBTree.h"
namespace bit
{
  template<class K>
  class set
  {
  public:
    struct SetKeyOfT
    {
      const K& operator()(const K& key)
      {
        return key;
      }
    };
    typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
    typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
    iterator begin() const
    {
      return _t.begin();
    }
    iterator end() const
    {
      return _t.end();
    }
    pair<iterator, bool> insert(const K& key)
    {
      return _t.Insert(key);
    }
  private:
    RBTree<K, K, SetKeyOfT> _t;
  };
}

注意这段代码:

typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;

 其中typenam是告诉编译器这里是类型因为这里是对类模板取内嵌类型。通过set的定义我们知道set不允许被修改数值,因此我们将两个迭代器实际上都定义为const_iterator。但是这样定义其中insert又出问题了,因为其中的返回类型会出现不匹配的情况,即pair<iterator, bool> 和_t.Insert(key)不匹配。因为我们return返回的实际上是iterator,而实际上接受的类型为const_iterator。这时我们上面提到的用pair构造了一个新的pair而不是拷贝构造了一个pair就起到作用了,他使得返回的类型匹配!


当然我们也有其他的解决办法:定义一个迭代器的拷贝构造

       STL库中的普通迭代器都可以转换为const迭代器,这是迭代器类的拷贝构造所支持的。

               如下:

struct __TreeIterator
{
  typedef RedBlackTreeNode<T> Node;
  Node* _node;
  typedef __TreeIterator<T,Ref,Ptr> Self;
  typedef __TreeIterator<T, T&, T*> iterator;
  __TreeIterator(const iterator& it)
    :_node(it._node)
  {}
  __TreeIterator(Node* node)
    :_node(node)
  {}
}

封装后的map

想较于set,map的key值不可修改,但是value是可以修改的,对于他的迭代器定义按照正常的const和非const就好,但是他主要做文章的地方是在RBTree<K, pair<const K, V>, MapKeyOfT> _t;中,直接将K定义为const K了。  

#pragma once
#include"RBTree.h"
namespace bit
{
  template<class K, class V>
  class map
  {
  public:
    struct MapKeyOfT
    {
      const K& operator()(const pair<K, V>& kv)
      {
        return kv.first;
      }
    };
    // 对类模板取内嵌类型,加typename告诉编译器这里是类型
    typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
    typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator 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();
    }
    V& operator[](const K& key)
    {
      pair<iterator, bool> ret = insert(make_pair(key, V()));
      return ret.first->second;
    }
    pair<iterator, bool> insert(const pair<K, V>& kv)
    {
      return _t.Insert(kv);
    }
  private:
    RBTree<K, pair<const K, V>, MapKeyOfT> _t;
  };
}

四、完整代码

RBTree.h
#pragma once
// set ->key
// map ->key/value
enum Colour
{
  RED,
  BLACK
};
template<class T>
struct RBTreeNode
{
  RBTreeNode<T>* _left;
  RBTreeNode<T>* _right;
  RBTreeNode<T>* _parent;
  T _data;
  Colour _col;
  RBTreeNode(const T& data)
    :_left(nullptr)
    , _right(nullptr)
    , _parent(nullptr)
    , _data(data)
    , _col(RED)
  {}
};
template<class T, class Ref, class Ptr>
struct __TreeIterator
{
  typedef RBTreeNode<T> Node;
  typedef __TreeIterator<T, Ref, Ptr> Self;
  Node* _node;
  __TreeIterator(Node* node)
    :_node(node)
  {}
  Ref operator*()
  {
    return _node->_data;
  }
  Ptr operator->()
  {
    return &_node->_data;
  }
  Self& operator--()
  {
    if (_node->_left)
    {
      Node* cur = _node->_left;
      while (cur->_right)
      {
        cur = cur->_right;
      }
      _node = cur;
    }
    else
    {
      Node* cur = _node;
      Node* parent = cur->_parent;
      while (parent && cur == parent->_left)
      {
        cur = parent;
        parent = parent->_parent;
      }
      _node = parent;
    }
    return *this;
  }
  Self& operator++()
  {
    if (_node->_right)
    {
      // 下一个就是右子树的最左节点
      Node* cur = _node->_right;
      while (cur->_left)
      {
        cur = cur->_left;
      }
      _node = cur;
    }
    else
    {
      // 左子树 根 右子树
      // 右为空,找孩子是父亲左的那个祖先
      Node* cur = _node;
      Node* parent = cur->_parent;
      while (parent && cur == parent->_right)
      {
        cur = parent;
        parent = parent->_parent;
      }
      _node = parent;
    }
    return *this;
  }
  bool operator!=(const Self& s)
  {
    return _node != s._node;
  }
  bool operator==(const Self& s)
  {
    return _node == s._node;
  }
};
// set->RBTree<K, K, SetKeyOfT> _t;
// map->RBTree<K, pair<const K, T>, MapKeyOfT> _t;
template<class K, class T, class KeyOfT>
class RBTree
{
  typedef RBTreeNode<T> Node;
public:
  typedef __TreeIterator<T, T&, T*> iterator;
  typedef __TreeIterator<T, const T&, const T*> const_iterator;
  iterator begin()
  {
    Node* cur = _root;
    while (cur && cur->_left)
    {
      cur = cur->_left;
    }
    return iterator(cur);
  }
  iterator end()
  {
    return iterator(nullptr);
  }
  const_iterator begin() const
  {
    Node* cur = _root;
    while (cur && cur->_left)
    {
      cur = cur->_left;
    }
    return const_iterator(cur);
  }
  const_iterator end() const
  {
    return const_iterator(nullptr);
  }
  //pair<iterator, bool> Insert(const T& data)
  pair<Node*, bool> Insert(const T& data)
  {
    if (_root == nullptr)
    {
      _root = new Node(data);
      _root->_col = BLACK;
      return make_pair(_root, true);
    }
    Node* parent = nullptr;
    Node* cur = _root;
    KeyOfT kot;
    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(cur, false);
      }
    }
    // 新增节点给红色
    cur = new Node(data);
    Node* newnode = cur;
    cur->_col = RED;
    if (kot(parent->_data) < kot(data))
    {
      parent->_right = cur;
      cur->_parent = parent;
    }
    else
    {
      parent->_left = cur;
      cur->_parent = parent;
    }
    while (parent && parent->_col == RED)
    {
      Node* grandfather = parent->_parent;
      if (parent == grandfather->_left)
      {
        //     g
        //   p   u
        // c
        Node* uncle = grandfather->_right;
        if (uncle && uncle->_col == RED)
        {
          // 变色
          parent->_col = uncle->_col = BLACK;
          grandfather->_col = RED;
          // 继续往上更新处理
          cur = grandfather;
          parent = cur->_parent;
        }
        else
        {
          if (cur == parent->_left)
          {
            // 单旋
            //     g
            //   p
            // c
            RotateR(grandfather);
            parent->_col = BLACK;
            grandfather->_col = RED;
          }
          else
          {
            // 双旋
            //     g
            //   p
            //     c
            RotateL(parent);
            RotateR(grandfather);
            cur->_col = BLACK;
            grandfather->_col = RED;
          }
          break;
        }
      }
      else  // parent == grandfather->_right
      {
        //     g
        //   u   p 
        //          c
        //
        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
          {
            //     g
            //   u   p 
            //     c
            //
            RotateR(parent);
            RotateL(grandfather);
            cur->_col = BLACK;
            grandfather->_col = RED;
          }
          break;
        }
      }
    }
    _root->_col = BLACK;
    return make_pair(newnode, true);
  }
  void RotateL(Node* parent)
  {
    Node* subR = parent->_right;
    Node* subRL = subR->_left;
    parent->_right = subRL;
    subR->_left = parent;
    Node* parentParent = parent->_parent;
    parent->_parent = subR;
    if (subRL)
      subRL->_parent = parent;
    if (_root == parent)
    {
      _root = subR;
      subR->_parent = nullptr;
    }
    else
    {
      if (parentParent->_left == parent)
      {
        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 (_root == parent)
    {
      _root = subL;
      subL->_parent = nullptr;
    }
    else
    {
      if (parentParent->_left == parent)
      {
        parentParent->_left = subL;
      }
      else
      {
        parentParent->_right = subL;
      }
      subL->_parent = parentParent;
    }
  }
  void InOrder()
  {
    _InOrder(_root);
    cout << endl;
  }
  void _InOrder(Node* root)
  {
    if (root == nullptr)
      return;
    _InOrder(root->_left);
    cout << root->_kv.first << " ";
    _InOrder(root->_right);
  }
  // 根节点->当前节点这条路径的黑色节点的数量
  bool Check(Node* root, int blacknum, const int refVal)
  {
    if (root == nullptr)
    {
      //cout << balcknum << endl;
      if (blacknum != refVal)
      {
        cout << "存在黑色节点数量不相等的路径" << endl;
        return false;
      }
      return true;
    }
    if (root->_col == RED && root->_parent->_col == RED)
    {
      cout << "有连续的红色节点" << endl;
      return false;
    }
    if (root->_col == BLACK)
    {
      ++blacknum;
    }
    return Check(root->_left, blacknum, refVal)
      && Check(root->_right, blacknum, refVal);
  }
  bool IsBalance()
  {
    if (_root == nullptr)
      return true;
    if (_root->_col == RED)
      return false;
    //参考值
    int refVal = 0;
    Node* cur = _root;
    while (cur)
    {
      if (cur->_col == BLACK)
      {
        ++refVal;
      }
      cur = cur->_left;
    }
    int blacknum = 0;
    return Check(_root, blacknum, refVal);
  }
  int Height()
  {
    return _Height(_root);
  }
  int _Height(Node* root)
  {
    if (root == nullptr)
      return 0;
    int leftHeight = _Height(root->_left);
    int rightHeight = _Height(root->_right);
    return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
  }
  size_t Size()
  {
    return _Size(_root);
  }
  size_t _Size(Node* root)
  {
    if (root == NULL)
      return 0;
    return _Size(root->_left)
      + _Size(root->_right) + 1;
  }
  Node * Find(const K & key)
  {
    Node* cur = _root;
    KeyOfT kot;
    while (cur!= nullptr)
    { 
      if (kot(cur->_data) < key)
      {
        cur = cur->_left;
      }
      else if (kot(cur->_data) > key)
      {
        cur = cur->_right;
      }
      else
      {
        return cur;
      }
    }
    return nullptr;
  }
private:
  Node* _root = nullptr;
};
myset.h
pragma once
#include"RBTree.h"
namespace bit
{
  template<class K>
  class set
  {
  public:
    struct SetKeyOfT
    {
      const K& operator()(const K& key)
      {
        return key;
      }
    };
    typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
    typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
    iterator begin() const
    {
      return _t.begin();
    }
    iterator end() const
    {
      return _t.end();
    }
    pair<iterator, bool> insert(const K& key)
    {
      return _t.Insert(key);
    }
  private:
    RBTree<K, K, SetKeyOfT> _t;
  };
}
mymap.h
#pragma once
#include"RBTree.h"
namespace bit
{
  template<class K, class V>
  class map
  {
  public:
    struct MapKeyOfT
    {
      const K& operator()(const pair<K, V>& kv)
      {
        return kv.first;
      }
    };
    // 对类模板取内嵌类型,加typename告诉编译器这里是类型
    typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
    typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator 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();
    }
    V& operator[](const K& key)
    {
      pair<iterator, bool> ret = insert(make_pair(key, V()));
      return ret.first->second;
    }
    pair<iterator, bool> insert(const pair<K, V>& kv)
    {
      return _t.Insert(kv);
    }
  private:
    RBTree<K, pair<const K, V>, MapKeyOfT> _t;
  };
}

感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

相关文章
|
4月前
|
算法 C语言 C++
C++语言学习指南:从新手到高手,一文带你领略系统编程的巅峰技艺!
【8月更文挑战第22天】C++由Bjarne Stroustrup于1985年创立,凭借卓越性能与灵活性,在系统编程、游戏开发等领域占据重要地位。它继承了C语言的高效性,并引入面向对象编程,使代码更模块化易管理。C++支持基本语法如变量声明与控制结构;通过`iostream`库实现输入输出;利用类与对象实现面向对象编程;提供模板增强代码复用性;具备异常处理机制确保程序健壮性;C++11引入现代化特性简化编程;标准模板库(STL)支持高效编程;多线程支持利用多核优势。虽然学习曲线陡峭,但掌握后可开启高性能编程大门。随着新标准如C++20的发展,C++持续演进,提供更多开发可能性。
83 0
|
2月前
|
编译器 C语言 C++
配置C++的学习环境
【10月更文挑战第18天】如果想要学习C++语言,那就需要配置必要的环境和相关的软件,才可以帮助自己更好的掌握语法知识。 一、本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。 二、文本编辑器 通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。 C++ 程序的源文件通常使用扩展名 .cpp、.cp 或 .c。 在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。 Visual Studio Code:虽然它是一个通用的文本编辑器,但它有很多插
|
2月前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
31 6
|
2月前
|
Java 编译器 C++
c++学习,和友元函数
本文讨论了C++中的友元函数、继承规则、运算符重载以及内存管理的重要性,并提到了指针在C++中的强大功能和使用时需要注意的问题。
23 1
|
3月前
|
数据安全/隐私保护 C语言 C++
C++(七)封装
本文档详细介绍了C++封装的概念及其应用。封装通过权限控制对外提供接口并隐藏内部数据,增强代码的安全性和可维护性。文档首先解释了`class`中的权限修饰符(`public`、`private`、`protected`)的作用,并通过示例展示了如何使用封装实现栈结构。接着介绍了构造器和析构器的使用方法,包括初始化列表的引入以及它们在内存管理和对象生命周期中的重要性。最后,通过分文件编程的方式展示了如何将类定义和实现分离,提高代码的模块化和复用性。
|
5月前
|
C++ 容器
【C++】map和set封装
【C++】map和set封装
40 2
|
5月前
|
存储 C++ 容器
【C++】开散列实现unordered_map与unordered_set的封装
【C++】开散列实现unordered_map与unordered_set的封装
57 0
|
7天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
22 2
|
13天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
41 5
|
19天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
49 4