[C/C++]详解STL容器9-基于红黑树模拟实现map和set
Posted TT在长大
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C/C++]详解STL容器9-基于红黑树模拟实现map和set相关的知识,希望对你有一定的参考价值。
本文基于红黑树模拟实现map和set,首先对之前模拟实现的红黑树做了一些改造,之后对map和set做了模拟实现。前文:[C/C++]详解STL容器7--红黑树的介绍及部分模拟实现_RMA515T的博客-CSDN博客
目录
一、红黑树的改造
因为关联式容器中存储的是<key, value>的键值对,因此k为key的类型,V如果是map,则为pair<K, V>; 如果是set,则为k;KeyOfV: 通过V来获取key的一个仿函数类。
节点类型
template<class T> //pair类型的T
struct RBTreeNode //节点结构体
RBTreeNode<T>* _left; //左子树
RBTreeNode<T>* _right; //右子树
RBTreeNode<T>* _parent; //父节点
T _data;
Colour _col;
RBTreeNode(const T& x) //构造函数
: _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(x)
, _col(RED)
;
迭代器
template<class T, class Ref, class Ptr>
struct __TreeIterator
typedef Ref reference;
typedef Ptr pointer;
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;
bool operator != (const Self& s) const
return _node != s._node;
bool operator == (const Self& s) const
return _node == s._node;
Self operator++()
if (_node->_right)
Node* left = _node->_right;
while (left->_left)
left = left->_left;
_node = left;
else
Node* cur = _node;
Node* parent = _node->_parent;
while (parent&& cur == parent->_right)
cur = cur->_parent;
parent = parent->_parent;
_node = parent;
return *this;
Self operator--()
if (_node->_left)
Node* right = _node->_left;
while (right->_left)
right = right->_left;
_node = right;
else
Node* cur = _node;
Node* parent = _node->_parent;
while (parent && cur == parent->_left)
cur = cur->_parent;
parent = parent->_parent;
_node = parent;
return *this;
;
反向迭代器
(这里写了一个反向迭代器适配器)
template<class Iterator>
struct ReverseIterator
typedef typename Iterator::reference Ref;
typedef typename Iterator::pointer Ptr;
typedef ReverseIterator<Iterator> Self;
Iterator _it;
ReverseIterator(Iterator it)
:_it(it)
Ref operator*() //*返回引用
return *_it;
Ptr operator->() //->返回指针 可以直接用
return _it.operator->();
bool operator != (const Self& s) const
return _it != s._it;
bool operator == (const Self& s) const
return _it == s._it;
Self operator++()
--_it;
return *this;
Self operator--()
++_it;
return *this;
;
改造后的红黑树
#pragma once
#include<iostream>
#include"RIterator.h"
using namespace std;
enum Colour //红黑树颜色枚举
RED,
BLACK,
;
template<class T> //pair类型的T
struct RBTreeNode //节点结构体
RBTreeNode<T>* _left; //左子树
RBTreeNode<T>* _right; //右子树
RBTreeNode<T>* _parent; //父节点
T _data;
Colour _col;
RBTreeNode(const T& x) //构造函数
: _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(x)
, _col(RED)
;
template<class T, class Ref, class Ptr>
struct __TreeIterator
typedef Ref reference;
typedef Ptr pointer;
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;
bool operator != (const Self& s) const
return _node != s._node;
bool operator == (const Self& s) const
return _node == s._node;
Self operator++()
if (_node->_right)
Node* left = _node->_right;
while (left->_left)
left = left->_left;
_node = left;
else
Node* cur = _node;
Node* parent = _node->_parent;
while (parent&& cur == parent->_right)
cur = cur->_parent;
parent = parent->_parent;
_node = parent;
return *this;
Self operator--()
if (_node->_left)
Node* right = _node->_left;
while (right->_left)
right = right->_left;
_node = right;
else
Node* cur = _node;
Node* parent = _node->_parent;
while (parent && cur == parent->_left)
cur = cur->_parent;
parent = parent->_parent;
_node = parent;
return *this;
;
template<class K, class T, class KeyOfT> //通过仿函数来取key的值进行比较
class RBTree
typedef RBTreeNode<T> Node;
private:
Node* _root;
void RotateR(Node* parent)
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* parentP = parent->_parent;
if (subLR) //左子树的右子树连接到父的右
subLR->_parent = parent;
parent->_left = subLR;
subL->_right = parent;
parent->_parent = subL;
// 如果parent是根节点,根新指向根节点的指针
if (parent == _root)
_root = subL;
subL->_parent = nullptr;
else
// 如果parent是子树,可能是其双亲的左子树,也可能是右子树
if (parentP->_left == parent)
parentP->_left = subL;
else
parentP->_right = subL;
subL->_parent = parentP;
void RotateL(Node* parent)
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* parentP = parent->_parent;
if (subRL)
subRL->_parent = parent;
parent->_right = subRL;
subR->_left = parent;
parent->_parent = subR;
// 如果parent是根节点,根新指向根节点的指针
if (parent == _root)
_root = subR;
subR->_parent = nullptr;
else
// 如果parent是子树,可能是其双亲的左子树,也可能是右子树
if (parentP->_left == parent)
parentP->_left = subR;
else
parentP->_right = subR;
subR->_parent = parentP;
void _InOrder(Node* root)
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_kv.first << ':' << root->_kv.second << endl;
_InOrder(root->_right);
bool _CheckBlance(Node* root, int BlackNum, int count)
if (root == nullptr)
if (count == BlackNum)
return true;
cout << "黑色节点的数量不相等" << endl;
return false;
if (root->_col == RED && root->_parent->_col == RED)
cout << "存在连续的红色节点" << endl;
return false;
if (root->_col == BLACK)
count++;
return _CheckBlance(root->_left, BlackNum, count) //递归处理每个边
&& _CheckBlance(root->_right, BlackNum, count);
void _Destory(Node* root)
if (root == nullptr)
return;
_Destory(root->_left);
_Destory(root->_right);
delete root;
public:
typedef __TreeIterator < T, T&, T* > iterator;
typedef __TreeIterator < T, const T&, const T* > const_iterator;
typedef ReverseIterator<iterator> reverse_iterator;
RBTree()
:_root(nullptr)
~RBTree()
_Destory(_root);
_root = nullptr;
reverse_iterator rbegin()
Node* right= _root;
while (right && right->_right) //最左
right = right->_right;
return reverse_iterator(right);
reverse_iterator rend()
return reverse_iterator(nullptr);
iterator begin()
Node* left = _root;
while (left && left->_left) //最左
left = left->_left;
return iterator(left);
iterator end()
return iterator(nullptr);
Node* Find(const K& key)
KeyOfT kot; //
Node* cur = _root;
while (cur)
if (kot(cur->_data) > key)
cur = cur->_left;
else if (kot(cur->_data) < 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* parent = nullptr;
Node* cur = _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);
Node* newNode = new Node(data);
newNode->_col = RED;
if (kot(parent->_data) > kot(data))
parent->_left = newNode;
newNode->_parent = parent;
else
parent->_right = newNode;
newNode->_parent = parent;
cur = newNode;
while (parent && parent->_col == RED) //违反规则三
Node* grandfather = parent->_parent;
if (parent == grandfather->_left) //左半边
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED) //情况一
uncle->_col = BLACK;
grandfather->_col = RED;
parent->_col = BLACK;
cur = grandfather; //迭代
parent = cur->_parent;
else //情况2.3
if (cur == parent->_left) //单侧
RotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
else //折
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
break; //黑色数量无变化,不需要向上
else // parent == grandfather->_right
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED) //情况一
uncle->_col = BLACK;
grandfather->_col = RED;
parent->_col = BLACK;
cur = grandfather; //迭代
parent = cur->_parent;
else //情况2.3
if (cur == parent->_right) //单侧
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
else //折
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
break;
_root->_col = BLACK; //插入结束再次将根变为黑
return make_pair(iterator(newNode), true);
bool CheckBlance() //检查是否为红黑树,每个路径的黑色节点数相等,
if (_root == nullptr)
return true;
if (_root->_col == RED)
return false;
int BlackNum = 0;
Node* left = _root; //找最左路径的黑节点个数,确定基准
while (left)
if (left->_col == BLACK)
BlackNum++;
left = left->_left;
int count = 0;
return _CheckBlance(_root, BlackNum, count);
void InOrder()
_InOrder(_root);
cout << endl;
;
二、map模拟实现
#pragma once
#include"RBTree.h"
namespace zht
template<class K, class V>
class map
struct MapKeyOfT //包装仿函数,重载()
const K& operator()(const pair<const 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>::reverse_iterator reverse_iterator;
reverse_iterator rbegin()
return _t.rbegin();
reverse_iterator rend()
return _t.rend();
iterator begin()
return _t.begin();
iterator end()
return _t.end();
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;
private:
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
;
三、set模拟实现
#pragma once
#pragma once
#include"RBTree.h"
namespace zht
template<class K, class V>
class set
struct SetKeyOfT //包装仿函数,重载()
const K& operator()(const K& key)
return key;
;
public:
typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::reverse_iterator reverse_iterator;
reverse_iterator rbegin()
return _t.rbegin();
reverse_iterator rend()
return _t.rend();
iterator begin()
return _t.begin();
iterator end()
return _t.end();
pair<iterator, bool> insert(const K& key)
return _t.Insert(key);
private:
RBTree<K, K, SetKeyOfT> _t;
;
总结
map和set的底层为红黑树,因此只需在内部封装一棵红黑树,即可将该容器实现出来。
以上是关于[C/C++]详解STL容器9-基于红黑树模拟实现map和set的主要内容,如果未能解决你的问题,请参考以下文章
[C/C++]详解STL容器9-基于红黑树模拟实现map和set
[C/C++]详解STL容器9-基于红黑树模拟实现map和set
[C/C++]详解STL容器7--红黑树的介绍及部分模拟实现
[C/C++]详解STL容器7--红黑树的介绍及部分模拟实现