(一)红黑树定义
红黑树的定义:
enum Colour { RED, BLACK }; template<class T> struct RBTreeNode { // 这里更新控制平衡也要加入parent指针 T _data; RBTreeNode<T>* _left; RBTreeNode<T>* _right; RBTreeNode<T>* _parent; Colour _col; RBTreeNode(const T& data) :_data(data) , _left(nullptr) , _right(nullptr) , _parent(nullptr) , _col(RED) {} }; 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(); Iterator end(); const_Iterator begin() const; const_Iterator end() const; pair<Iterator, bool> Insert(const T& data); private: Node* _root = nullptr; };
这里需要对Insert进行说明:
Insert返回的是pair<Iterator, bool>
若插入时存在该插入的data时,返回已存在结点的iterator和false。
若插入时不存在该data,则返回该新插入结点的iterator和true;
(二)红黑树的迭代器
红黑树迭代器的定义:
template<class T, class Ptr, class Ref> struct RBTreeIterator { typedef RBTreeNode<T> Node; typedef RBTreeIterator<T, T*, T&> Iterator; typedef RBTreeIterator<T, Ptr, Ref> Self; Node* _node; //构造函数,或者是拷贝构造,具体看实例化的对象是什么类型 RBTreeIterator(const Iterator& it) :_node(it._node) {} RBTreeIterator(Node* node) :_node(node) {} Self& operator++(); Self& operator--(); T& operator*(); T* operator->(); bool operator!=(const Self& s)const; bool operator==(const Self& s)const; };
1.operator++ 以及 oprator --
operator++ (按中序遍历):
若 原结点的右子树不为空,则访问该右树的最左结点;
若 原结点的右子树为空,则this这棵树访问完了,这就需要向上一级的子树移动,继续判断,这是一个循环的过程:只要当前节点是父节点的右子树根节点,则表示以父为根的子树访问完了,需要向上一级子树移动。直到当前结点为父节点的左孩子时停止访问(当前结点就是我们要的)。
Self& operator++() { //右边不为空 if (_node->_right) { Node* sub = _node->_right; while (sub->_left) { sub = sub->_left; } _node = sub; } else //右边为空 { Node* cur = _node; Node* parent = cur->_parent; while (parent && cur == parent->_right) { cur = parent; parent = cur->_parent; } _node = parent; } return *this; }
operator-- (按中序遍历):
若 原结点的左子树不为空,则访问该左树的最右结点;
若 原结点的左子树为空,则this这棵树访问完了,这就需要向上一级的子树移动,继续判断,这是一个循环的过程:只要当前节点是父节点的左子树根节点,则表示以父为根的子树访问完了,需要向上一级子树移动。直到当前结点为父节点的右孩子时停止访问(当前结点就是我们要的)。
Self& operator--() { if (_node->_left) { Node* sub = _node->_left; while (sub->_right) { sub = sub->_right; } _node = sub; } else { Node* cur = _node; Node parent = cur->_parent; while (parent && cur == parent->_left) { cur = parent; parent = cur->_parent; } _node = parent; } return *this; }
(三)map的封装
map的底层结构就是红黑树,因此在map中直接封装一棵红黑树,然后将其接口包装下即可
但是需要提供一个MapkeyofT类型,用于得到key,需要给红黑树进行插入时能得到key进行比较。
namespace xrw
{
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<const K, V>, MapKeyOfT>::Iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_Iterator const_iterator;
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 = insert(make_pair(key, V()));
return ret.first->second;
}
pair<iterator, bool> insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
private:
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
}
map的红黑树成员的类型 :
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
这里的是pair<const K, V>,因为在map中k的值不能改变,但value的值确是可以的,用上面这种方式控制红黑树类型非常巧妙,方便。
(四)set的封装
同样的set的底层结构就是红黑树,因此在map中直接封装一棵红黑树,然后将其接口包装下即可
但是需要提供一个MapkeyofT类型,用于得到key,需要给红黑树进行插入时能得到key进行比较。
namespace xrw
{
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K, K, SetKeyOfT>::const_Iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::const_Iterator const_iterator;
const_iterator begin() const
{
return _t.begin();
}
const_iterator end() const
{
return _t.end();
}
// iterator RBTree::const_iterator
pair<iterator, bool> insert(const K& key)
{
// pair<RBTree::iterator, bool>
//在底层红黑树中,调用insert会返回普通迭代器,所以此时需要将迭代器变成const类型的
pair<typename RBTree<K, K, SetKeyOfT>::Iterator, bool> ret = _t.Insert(key);
return pair<iterator, bool>(ret.first, ret.second);
//此处的会调用迭代器的构造函数,用于返回const的迭代器
}
private:
RBTree<K, K, SetKeyOfT> _t;
};
}
set的迭代器所指向的都是红黑树的const迭代器。