Cpp || 模拟实现map

map底层(RBTree.hpp)红黑树
#pragma  once
#include<iostream>
#include<functional>
using namespace std;
 
enum Color{
  Red,
  Black
};

template <class T>

struct RBTNode{
  RBTNode(const T& kv=T(),Color color=Red)
    :_kv(kv)
     ,_color(color)
     ,_left(nullptr)
     ,_right(nullptr)
     ,_parent(nullptr)
  {

  }
  T  _kv;
  Color _color;
  RBTNode<T>* _left;
  RBTNode<T>* _right;
  RBTNode<T>* _parent;
};

template <class T>
struct RBTreeIterator{
  typedef RBTNode<T> Node;
  typedef Node* pNode;
  typedef RBTreeIterator<T> Self;

  RBTreeIterator(pNode  PNode)
    :_pNode(PNode)
  {

  }

  RBTreeIterator()
    :_pNode(nullptr)
  {

  }

  RBTreeIterator(const Self&  s)
    :_pNode(s._pNode)
  {

  }
  //具有指针的操作
  T& operator*(){
    return _pNode->_kv;
  }

  T*  operator->(){
    //return &(operator*());
    //一般不直接取,通过解引用的方式来取地址
    return &_pNode->_kv;
  }

  //迭代器的移动
  //前置++
  Self& operator++(){
    Increament();
    return *this;
  }

  Self operator++(int){
    Self temp(*this);
    Increament();
    return temp;
  }

  //前置--
  Self& operator--(){
    DeIncreament();
    return *this;
  }

  Self operator--(int){
    Self temp(*this);
    DeIncreament();
    return temp;
  }

  bool operator==(const Self& s)const{
    return _pNode==s._pNode;
  }

  bool operator!=(const Self& s)const{
    return _pNode!=s._pNode;
  }

  private:

  void Increament(){
    if(_pNode->_right){
      _pNode=_pNode->_right;
      while(_pNode->_left){
        _pNode=_pNode->_left;
      }
    }else{
      //比_pNode大的元素可能在其双亲中
      Node* parent=_pNode->_parent;
      while(_pNode==parent->_right){
        _pNode=parent;
        parent=_pNode->_parent;
      }

      //根结点没有右子树,并且迭代器正好在根结点的位置
      if(_pNode->_right!=parent)
        _pNode=parent;
    }
  }

  void DeIncreament(){
    //end--能够走到最大节点的位置

    if (_pNode->_parent->_parent == _pNode&& Red==_pNode->_color){
    
      //当_pNode符合_pNode->_parent->_parent==_pNoded 
      //的时候说明_pNode是根结点或者_head,
      //_pNode->_color==Red则派出了_pNode是根结点的情况
      //则_pNode指向的是_head,其--指向了该树种最大的结点
      _pNode = _pNode->_right;
    }
    else if (_pNode->_left){
      //如果左子树存在,在左子树中找最大的节点
      _pNode = _pNode->_left;
      while (_pNode->_right){
        _pNode = _pNode->_right;
      }
    }
    else{
      //如果这个左子树不存在,就从该节点开始向上找
      Node* pParent = _pNode->_parent;
      while (_pNode == pParent->_left){
        _pNode = pParent;
        pParent = _pNode->_parent;
      }
      _pNode = pParent;
    }
  
  }
    private:
  Node* _pNode;
};

template <class K,class V,class KeyOfValue>

//因为关联式容器中的存储的是<Key,Value>的键值对,因此k为Key的类型
//ValueType:如果是map,则为pair<k,V>;如果是set,则为K
//KeyOfValue;通过value来获取key的一个仿函数
class RBTree{
  public:
    typedef RBTNode<V> Node;
    typedef Node*  pNode;
    typedef RBTreeIterator<V> Iterator;
   

    Iterator Begin(){
      return Iterator(_head->_left);
    }

    Iterator End(){
      return Iterator(_head);
    }

    Iterator Find(const V&data)const{
      pNode cur=_head->_parent;

      while(cur){
        if(KeyOfValue(data)==KeyOfValue(cur->_kv)){
          return Iterator(cur);
        
        }else if(KeyOfValue(data)<KeyOfValue(cur->_kv)) {
          cur=cur->_left;
        }else{
          cur=cur->_right;
        }
       return End();//没找到
    }
  }

    bool Empty()const{
      return _head->_parent==nullptr;
    }

    size_t Size()const{
      return _size;
    }
    /// 
    //Modify
    //在红黑树中插入data的键值对
    //若data中的key已经在红黑树中,则插入失败,返回<该结点的Iteator,false>
    //若data中的key不存在,则插入成功,返回<新的结点的迭代器,true>
    

  public:
    RBTree()
      :_size(0)
    {
      _head=new Node;
      _head->_left=_head;
      _head->_right=_head;
    }


    pair<Iterator,bool>  Insert(const V& kv){

      pNode pRoot=GetRoot();
      pNode pNewNode=nullptr;
    
      if(pRoot==nullptr){

        //第一次插入的时候插入的是根结点,且颜色为黑色
        /*pNode _root=new Node(kv);
        _root->_color=Black;
        _root->_parent=_head;
        _head->_left=_root;
        _head->_right=_root;
        _head->_parent=_root;
        return true;
        */
        pNewNode=pRoot=new Node(kv,Black);
        pRoot->_parent=_head;
        _head->_parent=pRoot;
        _head->_left=pRoot;
        _head->_right=pRoot;
        ++_size;
        return make_pair(Iterator(pNewNode),true);
      }
      else 
      {  //处理存在根结点的情况


        pNode cur=pRoot;
        KeyOfValue keyofvalue;
        pNode parent=nullptr;
        while(cur){
          parent=cur;
          if(KeyOfValue(cur->_kv)>KeyOfValue(kv)){
          
            cur=cur->_left;
          }else if(KeyOfValue(kv)>KeyOfValue(cur->_kv)){

            cur=cur->_right;
          }else{
            return make_pair(Iterator(cur),false);
          }
        }

        //进行插入
       pNewNode=cur=new Node(kv);


        if(KeyOfValue(cur->_kv)<KeyOfValue(parent->_kv)){
          parent->_left=cur;
        }else{
          parent->_right=cur;
        }

        cur->_parent=parent;

        //进行调整变色
        while(cur!=pRoot && parent->_color==Red){
   
          pNode gparent=parent->_parent;
          if(gparent->_left==parent){
            pNode uncle=gparent->_right;
            //u存在且为红
            if(uncle && uncle->_color==Red){
              //情况一
              parent->_color=Black;
              uncle->_color=Black;
              gparent->_color=Red;
              cur=gparent;
              parent=cur->_parent;
            }else{
              //u不存在 / 存在且为黑
              //1.以g为轴右旋
              //2.调整颜色,p为黑色,g为红色

              //检查是否为双旋场景:左右双旋
              if(parent->_right==cur){
                RotateL(parent);
                swap(parent,cur);
              }
              RotateR(gparent);
              parent->_color=Black;
              gparent->_color=Red;
              break;
            }
          }else{
            pNode uncle=gparent->_left;
            if(uncle && uncle->_color==Red){
              parent->_color=uncle->_color=Black;
              gparent->_color=Red;
              cur=gparent;
              parent=cur->_parent;

            }else{
              //u存在且为黑/u不存在
              if(parent->_left==cur){
                RotateR(parent);
                swap(cur,parent);
              }

              RotateL(gparent);
              gparent->_color=Red;
              parent->_color=Black;
              break; 
            }
          }
        }
      } 

      ++_size;
      //红黑树根始终是黑色的
      pRoot->_color=Black;
      //为了实现后续的迭代器,将head的左右指针指向最大,最小的值
      _head->_left=leftMost();
      _head->_right=rightMost();

      return make_pair(Iterator(pNewNode),true); 

    }

    pNode leftMost(){

      pNode pRoot=GetRoot();

      if(pRoot==nullptr){
        return _head;
      }
      pNode cur=pRoot;
      while(cur && cur->_left){
        cur=cur->_left;
      }
      return cur;
    }

    pNode rightMost(){

      pNode pRoot=GetRoot();
      if(pRoot==nullptr){
        return _head;
      }
      pNode cur=pRoot;
      while(cur && cur->_right){
        cur=cur->_right;
      }
      return cur;
    }

    void RotateL(pNode parent){
      pNode subR=parent->_right;
      pNode subRL=subR->_left;

      subR->_left=parent;
      parent->_right=subRL;

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

      if(parent!=_head->_parent){
        pNode gparent=parent->_parent;

        //判断parent之前是parent->_parent 的那一边的结点
        //把subR链接到对应的边
        if(gparent->_left==parent)
          gparent->_left=subR;
        else 
          gparent->_right=subR;
        //更新subR的parent
        subR->_parent=gparent;
      }
      else {
        //如果parent是根,subR变成新的根
        subR->_parent=_head;
        _head->_parent=subR;
      }

      //链接subR与parent
      parent->_parent=subR;      
    }

   void RotateR(pNode parent){
     pNode subL=parent->_left;
     pNode subLR=subL->_right;

     //1.单向链接subL,subLR,parent
     subL->_right=parent;
     parent->_left=subLR; 
     //2.向上链接subLR,parent 
     if(subLR){
       subLR->_parent=parent;
     }
     //3.双向链接subL与parent<_parent 
     if(parent!=_head->_parent){
       pNode gParent=parent->_parent;

       if(gParent->_left==parent){
         gParent->_left=subL;
       }else{
         gParent->_right=subL; 
       }

       //把subL的父亲结点改成其祖宗结点
       subL->_parent=gParent;
     }else{
       subL->_parent=_head;
       _head->_parent=subL; 
     }
     //4.向上链接parent,subL 
     parent->_parent=subL;
   }



    void Inorder(){
      _Inorder(_head->_parent);
      cout<<endl;
    }

    bool IsValidRBTree()
    {
      pNode pRoot = GetRoot();

      // 空树也是红黑树
      if (nullptr == pRoot)
        return true;

        // 检测根节点是否满足情况
        if (Black != pRoot->_color)
        {
          cout << "违反红黑树性质一:根节点必须为黑色!" << endl;
          return false;
        }
      // 获取任意一条路径中黑色节点的个数
      size_t blackCount = 0;
      pNode pCur = pRoot;
      while (pCur)
      {
        if (Black == pCur->_color)
          blackCount++;
        pCur = pCur->_left;
      }
      // 检测是否满足红黑树的性质,k用来记录路径中黑色节点的个数
      size_t k = 0;
      return _IsValidRBTree(pRoot, k, blackCount);
    }

  private:
    void _Inorder(pNode parent){
      if(parent){
        _Inorder(parent->_left);
        cout<<"Key:"<<parent->_kv.first<<"Value:"<<parent->_kv.second<<endl;
        _Inorder(parent->_right);
      }
    }

    pNode& GetRoot(){
      return _head->_parent;
    }

    
    bool _IsValidRBTree(pNode pRoot, size_t k, const size_t blackCount) {
      //走到null之后,判断k和black是否相等
      if (nullptr == pRoot)
      {
        if (k != blackCount)
        {
          cout << "违反性质四:每条路径中黑色节点的个数必须相同" << endl;
          return false;
        }
        return true;
      }

      // 统计黑色节点的个数
      if (Black == pRoot->_color)
        k++;
      // 检测当前节点与其双亲是否都为红色
      pNode pParent = pRoot->_parent;
      if (pParent && Red == pParent->_color && Red == pRoot->_color)
      {
        cout << "违反性质三:没有连在一起的红色节点" << endl;
        return false;
      }
      return _IsValidRBTree(pRoot->_left, k, blackCount) &&
        _IsValidRBTree(pRoot->_right, k, blackCount);
    }

  private:
    pNode _head;
    size_t _size;  //用于记录有效结点个数
};
用于封装底层红黑树的Map_RBTree.hpp
#include"RBTree.hpp"
#include<string>

namespace bite{
  //封装红黑树
  template <class K,class V>
    class Map{
      typedef pair<K,V> ValueType;

      //该内部类的作用是:将value中的key提取出来
      struct KeyOfValue{
       const K&operator()(const ValueType& data){
         return data.first;
        }
      };

 
      public:
     typedef typename   RBTree<K,pair<K,V>,ValueType>::Iterator Iterator;

      public:
      Map()
        :_t()
      {

      }
      Iterator begin(){
        return _t.Begin();
      }

      Iterator end(){
        return _t.End();
      }

      size_t size()const{
        return _t.Size();
      }

      bool empty()const{
        return _t.Empty();
      }

      Iterator find(const K& key){
        return _t.Find(make_pair(key,V()));
      }

      //下标运算符
      V& operator[](const K& key){
        pair<Iterator,bool> ret=Insert(make_pair(key,V()));
        return ret.first->second;
        //ret.first.operator->()->second;
      }

      const V& operator[](const K& key)const{
        return ( _t.Insert(make_pair(key,V()) ).first)->second;
      }

      pair<Iterator,bool> Insert(const ValueType& data){
        return _t.Insert(data);
      }
      private:
        RBTree<K,pair<K,V>,ValueType> _t;
    };
}
用于测试模拟实现map的代码
  • 此处只是测试了部分接口
#include"Map_RBTree.hpp"

void testMap(){
  bite::Map<int ,string> m;
  m.Insert(pair<int,string>(1, "你好"));
  //m.Insert(pair<int,string>(2,"中国"));
  //m.Insert(pair<int,string>(3,"中国"));
  m.Insert(pair<int,string>(4,"将来"));
  m.Insert(make_pair(2,"比特"));

  m[3] = "中国";

  bite::Map<int,string>::Iterator t=m.begin(); 
  while(t!=m.end()){
    cout<<t->first<<" "<<t->second<<endl;
    t++;
  }
  cout<<"该容器中存储的键值对个数:"<<m.size()<<endl;
}

int main(){
  testMap();
  return 0;
}
  1. 对于map[n]=x的执行过程的讲解
  • 由调试我们可以发现,该过程执行步骤如下
  1. 首先执行operator[]操作,其内部是将键值和V()进行插入
  2. 再对插入过程的返回值的first执行operator()操作取到_pNode->kv
  3. 再取其键值对中的second返回,之后将V()使用x进行代替
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值