树结点的定义
map和set的底层都是红黑树,由于set是Key型,而map是key-value型,这就需要我们的红黑树是一种泛型,实现set时树节点内存放的值时Key,当实现map时树结点所储存的值就需要是存放Key-value的值的pair类型.
因此我们应该这样定义红黑树的结点、
template <class V>
class RBTreeNode
{
public:
RBTreeNode* _left;
RBTreeNode* _parent;
RBTreeNode* _right;
Color _color;
V _data; //根据传入类型来确定存储值
RBTreeNode(const V& data)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_data(data)
,_color(RED)
{
}
};
红黑树的定义
包含了构造红黑树的过程以及旋转操作:不懂可以看看我的红黑树和AVL树的笔记
template<class K,class V,class KeyOfValue>
class RBTree
{
typedef RBTreeNode<V> Node;
KeyOfValue kov;
public:
typedef __Tree_iterator<V,V*,V&> iterator;
typedef __Tree_iterator<V,const V*,const V&> const_iterator; //const类型迭代器
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);
}
Node* Find(const K& key)
{
Node* cur = _root;
KeyOfValue kot;
while (cur)
{
if (kot(cur->_data) < key)
{
cur = cur->_right;
}
else if (kot(cur->_data) > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
pair<iterator,bool> Insert(const V& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_color = BLACK;
return make_pair(iterator(_root),true);
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (kov(cur->_data) < kov(data))
{
parent = cur;
cur = cur->_right;
}
else if (kov(cur->_data) > kov(data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur), false);
}
}
//到达插入位置
cur = new Node(data);
cur->_color = RED;
Node* newnode = cur;
if ( kov(parent->_data) < kov(cur->_data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
//开始构建红黑树
while (parent && parent->_color == RED)//父亲存在并且颜色为红色
{
Node* grandfather = parent->_parent; //找到祖父结点
if (parent == grandfather->_left) //如果父亲是祖父的左孩子
{
Node* uncle = grandfather->_right; //叔叔就是祖父的有孩子
if (uncle && uncle->_color == RED) //如果叔叔存在并且叔叔的颜色为红色
{
parent->_color = BLACK; //将父亲和叔叔改为黑色 将祖父改为红色
uncle->_color = BLACK;
grandfather->_color = RED;
cur = grandfather; //继续向上更新
parent = cur->_parent;
}
else ////如果叔叔不存在或者叔叔的颜色为黑色 就需要进行旋转
{
if (cur == parent->_left) //因为 父亲是祖父的左孩子 如果cur是父亲的的左孩子 (左左) 只需要进行右单旋
{
RotateR(grandfather);
//旋转后跟新结点颜色
grandfather->_color = RED;
parent->_color = BLACK;
}
else //父亲是祖父的左孩子 如果cur是父亲的的右孩子 (左右) 先进行左旋 在进行右旋
{
RotateL(parent);
RotateR(grandfather);
//旋转后跟新结点颜色
grandfather->_color = RED;
cur->_color = BLACK;
}
break;
}
}
else//parent == grandfather->_right 如果父亲是祖父的孩子
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_color == RED) //叔叔存在并且为红色
{
parent->_color = BLACK; //将父亲和叔叔改为黑色 将祖父改为红色
uncle->_color = BLACK;
grandfather->_color = RED;
cur = grandfather; //继续向上更新
parent = cur->_parent;
}
else ///如果叔叔不存在或者叔叔的颜色为黑色 就需要进行旋转
{
if (cur == parent->_right) //因为 父亲是祖父的右孩子 如果cur是父亲的的右孩子 (右右) 只需要进行左单旋
{
RotateL(grandfather);
grandfather->_color = RED;
parent->_color = BLACK;
}
else// 父亲是祖父的右孩子 如果cur是父亲的的左孩子 (右左) 先进行右单旋 再 进行左单旋
{
RotateR(parent);
RotateL(grandfather);
grandfather->_color = RED;
cur->_color = BLACK;
}
break;
}
}
}
_root->_color = BLACK;
return make_pair(iterator(newnode), true);
}
private:
void RotateR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
parent->_left = curright;
if (curright)
{
curright->_parent = parent;
}
cur->_right = parent;
Node* ppNode = parent->_parent;
parent->_parent = cur;
if (ppNode == nullptr)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = cur;
}
else
{
ppNode->_right = cur;
}
cur->_parent = ppNode;
}
}
void RotateL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
parent->_right = curleft;
if (curleft)
{
curleft->_parent = parent;
}
cur->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = cur;
if (ppNode == nullptr)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = cur;
}
else
{
ppNode->_right = cur;
}
cur->_parent = ppNode;
}
}
Node* _root = nullptr;
};
在图中我们看见在类模板中除了K和V我们发现还有一个KeyOfValue的类型,这是干什么的呢?
其实他是一个仿函数,为了我们方便从结点中的V类型提取我们所需要的Key值,当此红黑树用来定义set时,树结点中存放的V的类型就是K,用KeyOfValue来获取key值,当用来实现map时,用KeyOfValue来获取pair类型中的Key值。他的具体定义会在map和set的定义中实现。
map和set的迭代器
++操作
在实现迭代器的过程中最困难的部分就是迭代器的++和--操作
++操作该怎么做呢(它的核心本质就是树的中序 左子树 根 右子树)
我们分为两种情况:第一 当目前结点的右孩子不为空时,我们只需要去寻找当前结点右子树的最小值,第二种情况 当目前结点的右孩子为空时,我们需要找到下一个结点应该是 ---当前结点是其父亲的左指针 那么下一个结点就是当前结点的父亲,如果当前结点是其父亲的右指针,那么我们就继续向上更新 ,寻找下一个结点
template<class V>
struct __Tree_iterator
{
typedef RBTreeNode<V> Node;
typedef __Tree_iterator<V> Self;
Node* _node;
__Tree_iterator(Node* node)
:_node(node)
{
}
bool operator!=(const Self& v)
{
return _node != v._node;
}
V& operator*()
{
return _node->_data;
}
V* operator->()
{
return &(_node->_data);
}
Self& operator++()
{
if (_node->_right)
{
Node* it = _node->_right;
while (it->_left)
{
it = it->_left;
}
_node = it;
}
else
{
Node* cur = _node;
Node* parent = _node->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
};
--操作
--的操作方法和++的方法是相反的
同样我们分为两种情况:第一种:当前结点的左子树如果不为空,那么下一个访问结点就是当前结点左子树的最大值,第二种情况:当前结点的左子树为空。我们就需要更新cur(更新当前节点)和parent,直到cur是其父亲结点的右子树,那么下一个访问结点就是cur的父亲结点
Self& operator--()
{
if (_node->_left)
{
Node* subright = _node->_left;
while (subright->_right)
{
subright->_right;
}
_node = subright;
}
else
{
Node* cur = _node;
Node* parent = _node->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
迭代器的定义及其他操作
template<class V,class Ptr,class Ref>
struct __Tree_iterator
{
typedef RBTreeNode<V> Node;
typedef __Tree_iterator<V ,Ptr, Ref> Self;
typedef __Tree_iterator<V, V*, V&> iterator; //此处的typedef是为了
//用普通迭代器构造const迭代器
Node* _node;
__Tree_iterator(Node* node)
:_node(node)
{
}
__Tree_iterator( const iterator& it) //如果是普通迭代器那么这是拷贝构造
:_node(it._node) // 如果是const迭代器那么这是 一种构造函数 用于将
{ //普通迭代器构造成const迭代器
}
bool operator!=(const Self& v)
{
return _node != v._node;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &(_node->_data);
}
};
set的模拟实现
set的封装:
template<class K>
class set
{
struct SetOfValue
{
K operator()(const K& key)
{
return key ;
}
};
public:
typedef typename RBTree<K,K, SetOfValue>::const_iterator iterator;
typedef typename RBTree<K,K, SetOfValue>::const_iterator const_iterator;
iterator begin() const
{
return t.begin();
}
iterator end() const
{
return t.end();
}
pair<iterator,bool> Insert(const K& key)
{
pair< typename RBTree<K, K, SetOfValue>::iterator , bool> ret = t.Insert(key);
return pair < iterator, bool >(ret.first, ret.second);
}
private:
RBTree<K, K, SetOfValue> t;
};
因为set是不可修改的容器所以我们的普通迭代器和const迭代器都是const迭代器,inser的返回了类型是pair类型,由于在set中的迭代器是const迭代器,而在调用insert函数时,t 是普通对象,所以返回的是普通迭代器的对象,因此才需要了在定义迭代器是需要将普通迭代器构造成const迭代器的构造函数,所以在insert函数中,我们先接受普通迭代器的pair类型,再用普通迭代器来构造const迭代器。
map的模拟实现
map的封装:
template<class K, class V>
class map
{
struct MapOfValue
{
K operator()(const pair<const K,V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree<K, pair<const K, V>, MapOfValue>::iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapOfValue>::const_iterator const_iterator;
//typedef typename RBTree<K, pair<K, V>, MapOfValue>::iterator iterator;
pair<iterator,bool> Insert(const pair<const K, V>& kv)
{
return t.Insert(kv);
}
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 = t.Insert(make_pair(key,V()));
return ret.first->second;
}
private:
RBTree<K, pair<const K,V>,MapOfValue> t;
};
在map中应为Key值是不可以修改的,而Value时可以修改的,所以我们在定义时就将pair类中的Key定义为const。

1497

被折叠的 条评论
为什么被折叠?



