前言
在之前的讲解中我们了解到了关于set和map的简单使用set和map的模拟使用,本次我们来基于上节课的模拟实现的红黑树来对对map和set进行模拟实现!!!
正文开始
一、红黑树模拟实现STL中的map与set
首先我们先来看看STL库中是如何实现map和set的
我们在来看看库里面的红黑树是如何实现的
红黑树底层并不知道你给我传过来的参数是什么并不知道!(并不知道你是set还是map)
set—>rb_tree<K,K>
map–>rb_tree<K,pair<K,V>>
大家可能会觉得对于set传入两个参数可能会有点浪费,但是没办法,因为红黑树还要去兼容map这个数据结构。
所以到底是set和map是由红黑树的第二个模板参数决定的!!!
这里会有人说了,那这第一个模板参数是不是就没有用了?
因为我们要用尽量少的资源去实现更多的资源,我们在这里用一颗红黑树去同时实现了set和map!!!
这里和迭代器的实现也有关系!
1.1 红黑树的迭代器
迭代器的好处是可以方便遍历,是数据结构的底层实现与用户透明。如果想要给红黑树增加迭代
器,需要考虑以前问题:
- begin()与end()
STL明确规定,begin()与end()代表的是一段前闭后开的区间,而对红黑树进行中序遍历后,可以得到一个有序的序列,因此:begin()可以放在红黑树中最小节点(即最左侧节点)的位置,end()放在最大节点(最右侧节点)的下一个位置
end()我们定义为nullptr;
我们的实现简化了这一块
- operator++()与operator–()
对于operator++我们要的就是该树的中序遍历的下一个节点,就是我迭代器++的位置
那我们如何找中序的下一个位置呢?
首先判断右子树是否为空
1.如果为空,要找该节点是祖先的左节点的祖先节点
2.非空–>右子树的最左节点
Self& operator++()
{
if (_node->_right == nullptr)
{
//找该节点是祖先的左节点的祖先节点
Node* cur = _node;
Node* parent = cur->_parent;
while (parent&& parent->_right==cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
else
{
//右子树的最左节点
Node* subLeft = _node->_right;
while (subLeft->_left)
{
subLeft = subLeft->_left;
}
_node = subLeft;
}
return *this;
}
对于operator–我们要的就是该树的中序遍历的上一个节点,就是我迭代器–的位置
那我们如何找中序的下一个位置呢?
首先判断左子树是否为空
1.如果为空,要找该节点是祖先的右节点的祖先节点
2.非空–>左子树的最右节点
Self& operator--()
{
if (_node->_left == nullptr)
{
//找该节点是祖先的右节点的祖先节点
Node* cur = _node;
Node* parent = cur->_parent;
while (parent&&parent->_left == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
else
{
//找左子树的最右节点
Node* subRight = _node->_left;
while (subRight->_right)
{
subRight = subRight->_right;
}
_node = subRight;
}
}
1.2 改造红黑树
因为关联式容器中存储的是<key, value>的键值对,因此
k为key的类型,
ValueType: 如果是map,则为pair<K, V>; 如果是set,则为k
KeyOfValue: 通过value来获取key的一个仿函数类
//T决定红黑树存什么数据
//set RBTree<K,K>
//map RBTree<K,pair<K,T>
//KeyOfT判断传进来的参数是K还是T
template<class K, class T,class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef __RBTreeIterator<T, T&,T*> iterator;
typedef __RBTreeIterator<T, const T&,const T*> const_iterator;
iterator Begin()
{
Node* subLeft = _root;
while (subLeft && subLeft->_left)
{
subLeft = subLeft->_left;
}
return iterator(subLeft);
}
iterator End()
{
return iterator(nullptr);
}
const_iterator Begin()const
{
Node* subLeft = _root;
while (subLeft && subLeft->_left)
{
subLeft = subLeft->_left;
}
return const_iterator(subLeft);
}
const_iterator End()const
{
return const_iterator(nullptr);
}
pair<iterator,bool> insert(const T& data)
{
//1.搜索树的规则插入
//2.看是否违反平衡规则,如果违反就需要处理:旋转
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);
}
}
cur = new Node(data);
Node* newNode = cur;
cur->_col = RED;
if (kot(parent->_data) > kot(data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
//调节关键看叔叔
//存在连续的红色节点,违反规则三,需要处理
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
if (grandfather->_left == parent)
{
Node* uncle = grandfather->_right;
//情况一:
if (uncle && uncle->_col == RED)//叔叔存在且为红
{
//变色
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
//继续向上处理
cur = grandfather;
parent = cur->_parent;
}
else//叔叔不存在或者叔叔且为黑
{
//情况二
if (cur == parent->_left)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
//情况三
else//双旋
{
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_left;
//情况一:
if (uncle && uncle->_col == RED)//叔叔存在且为红
{
//变色
parent->_col = BLACK;
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//双旋
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return make_pair(iterator(newNode), true);
}
//情况二和情况三旋转+变色以后,这颗字数不违反红黑树规则,相比插入前,黑色节点的数量是不变的,不会影响上层,处理就结束了
iterator Find(const K& key)
{
Node* cur = _root;
KeyOfT kot;
while (cur)
{
if (kot(cur->_data) < key)
{
cur = cur->_right;
}
else if(kot(cur->_data) > key)
{
cur = cur->_left;
}
else
{
return iterator(cur);
}
}
return End();
}
private:
//左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (parent == _root)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if (parent==ppNode->_left )
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
}
//右单旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (_root == parent)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
private:
Node* _root = nullptr;
};
1.3 set的模拟实现
set的底层为红黑树,因此只需在set内部封装一棵红黑树,即可将该容器实现出来。
namespace hulu
{
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& k)
{
return k;
}
};
public:
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
pair<iterator,bool> insert(const K& key)
{
pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.insert(key);
return pair<iterator, bool>(iterator(ret.first._node),ret.second);
}
iterator begin()const
{
return _t.Begin();
}
iterator end()const
{
return _t.End();
}
iterator find(const K& key)
{
return _t.Find(key);
}
private:
RBTree<K, K, SetKeyOfT> _t;
};
}
1.4 map的模拟实现
map的底层结构就是红黑树,因此在map中直接封装一棵红黑树,然后将其接口包装下即可。
namespace hulu
{
template<class K,class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<K,V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::const_iterator const_iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
pair<iterator, bool> insert(const pair<K, V>& kv)
{
return _t.insert(kv);
}
iterator find(const K& key)
{
return _t.Find(key);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert(make_pair(key,V()));
return ret.first->second;
}
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t;
};
}
附录
迭代器的实现
template<class T,class Ref,class Ptr>
struct __RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef __RBTreeIterator<T, Ref, Ptr> Self;
__RBTreeIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()
{
if (_node->_right == nullptr)
{
//找该节点是祖先的左节点的祖先节点
Node* cur = _node;
Node* parent = cur->_parent;
while (parent&& parent->_right==cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
else
{
//右子树的最左节点
Node* subLeft = _node->_right;
while (subLeft->_left)
{
subLeft = subLeft->_left;
}
_node = subLeft;
}
return *this;
}
Self operator++(int)
{
Self tmp(*this);
++(*this);
return *this;
}
Self& operator--()
{
if (_node->_left == nullptr)
{
//找该节点是祖先的右节点的祖先节点
Node* cur = _node;
Node* parent = cur->_parent;
while (parent&&parent->_left == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
else
{
//找左子树的最右节点
Node* subRight = _node->_left;
while (subRight->_right)
{
subRight = subRight->_right;
}
_node = subRight;
}
}
Self operator--(int)
{
Self tmp(*this);
--(*this);
return *this;
}
bool operator!=(const Self& s)const
{
return _node != s._node;
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
Node* _node;
};
(本章完!)