C++红黑树模拟实现map和set(3)

简介: C++红黑树模拟实现map和set(3)

三、map和set的实现


1、红黑树的实现


  • 具体实现代码:


//颜色
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& 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&, T*> iterator;
  typedef _TreeIterator<T,const T&, 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&&cur->_left)
    {
      cur = cur->_left;
    }
    return iterator(cur);
  }
  reverse_iterator rbegin()
  {
    Node* cur = _root;
    while (cur&&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& 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& 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 && parent->_col == RED)
    {
      //此时当前节点一定有祖父节点
      Node* granparent = parent->_parent;
      //具体调整情况主要看叔叔节点
      //分左右讨论
      if (parent == granparent->_left)
      {
        Node* uncle = granparent->_right;
        //情况1:叔叔节点存在且为红
        if (uncle && 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 && 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*& 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 && root->_parent->_col == RED)
    {
      cout << "存在连续红色节点" << endl;
      return false;
    }
    if (root->_col == BLACK)
      count++;
    return _IsRBTree(root->_left, blacknum, count) && _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;
};


2、map的封装


  • 具体实现代码



namespace cole
{
  template<class K, class V>
  class map
  {
    struct MapOfKey
    {
      const K& operator()(const pair<K, V>& 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>& kv)
    {
      return _t.Insert(kv);
    }
    V& operator[](const K& key)
    {
      pair<iterator, bool> ret = insert(make_pair(key, V()));
      return ret.first->second;
    }
    iterator find(const K& key)
    {
      return _t.Find(key);
    }
  private:
    RBTree<K, pair<const K, V>, MapOfKey> _t;
  };
}


3、set的封装


  • 具体实现代码:


namespace cole
{
  template<class K>
  class set
  {
    struct SetOfKey
    {
      const K& operator()(const K& 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& key)
    {
      return _t.Insert(key);
    }
    iterator find(const K& key)
    {
      return _t.Find(key);
    }
  private:
    RBTree<K, K, SetOfKey> _t;
  };
}
相关文章
|
17天前
|
算法
你对Collection中Set、List、Map理解?
你对Collection中Set、List、Map理解?
52 18
你对Collection中Set、List、Map理解?
|
11天前
|
存储 缓存 安全
只会“有序无序”?面试官嫌弃的List、Set、Map回答!
小米,一位热衷于技术分享的程序员,通过与朋友小林的对话,详细解析了Java面试中常见的List、Set、Map三者之间的区别,不仅涵盖了它们的基本特性,还深入探讨了各自的实现原理及应用场景,帮助面试者更好地准备相关问题。
49 20
|
28天前
|
存储 C++ 容器
【C++】map、set基本用法
本文介绍了C++ STL中的`map`和`set`两种关联容器。`map`用于存储键值对,每个键唯一;而`set`存储唯一元素,不包含值。两者均基于红黑树实现,支持高效的查找、插入和删除操作。文中详细列举了它们的构造方法、迭代器、容量检查、元素修改等常用接口,并简要对比了`map`与`set`的主要差异。此外,还介绍了允许重复元素的`multiset`和`multimap`。
30 3
【C++】map、set基本用法
|
28天前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
22 5
|
28天前
|
存储 C++ 容器
【C++】map的模拟实现
C++中的`map`是STL中的一种关联容器,存储键值对且键唯一。`map`基于红黑树实现,自动按键排序,支持动态调整、复杂数据类型、丰富的成员函数及双向迭代器。插入、查找等操作保证了对数时间复杂度,适用于需要快速查找和有序存储的场景。
22 3
|
28天前
|
存储 C++ 容器
【C++】set模拟实现
C++中的`set`是STL提供的一种关联容器,用于存储唯一元素并自动按特定顺序(默认升序)排序。其内部通过红黑树实现,保证了高效的插入、删除和查找操作,时间复杂度均为O(log n)。`set`支持迭代器遍历,提供了良好的数据访问接口。
31 3
|
25天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
42 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
84 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
81 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
88 4