基建改造
template<class K, class T,class KeyofT>
class RBTree
{
//类域中重命名 typedef 如果想让类外面用到,就加public修饰。
....
}
- 为了兼容set和map,对于第一个参数我们是用来比较的key类型,第二个参数是用来储存数据的类型
- 由于set使用的是K。map使用的K是pair<k,v>中的first;红黑树这个类模板,也不知道这个类型到底具体是什么,所以再增加一个仿函数类型模板参数,获取K的类型。
template<class T>
struct RBTreeNode
{
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
T _data;
Colour _col;
RBTreeNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
, _col(RED)
{
}
};
红黑树的迭代器
用一个节点的指针初始化成迭代器,实现对STL所有容器进行统一方式的访问。
T,T&,T*
;iterator
要确保和官方迭代器名字一致就可以用范围for。*it
(迭代器),拿到这个指针里面的数据。!=
就是两个节点的指针不相等
- 红黑树的
++
:访问到容器的下一个节点: - 红黑树的
begin
则应该是中序里最左边的一个节点。++
,看begin
的右侧,有的话,找右子树里面最左面的一个。- 若右侧也没有:代表我这一层的左子树右子树访问结束。返回上一层。
- 由于这一层是从上一层的左子树下来的,要看当前节点是不是双亲结点的左侧;
- 不是则一直迭代往上走;
- 是就返回双亲结点。
template<class T, class Ref, class Ptr>
struct RBTreeiterator
{
typedef RBTreeNode<T> Node;...
typedef RBTreeiterator<T, Ref, Ptr> Self;
Node* _node;
RBTreeiterator(Node* node = nullptr)
:_node(node)
{
}
//*it 对一个指针解引用,取到的是节点里面的数据
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
//红黑树迭代器的前置++ 返回是自增以后的迭代器
Self& operator++()
{
if (_node->_right)
{
//右边存在,找右子树最左边的那个节点
Node* subRL = _node->_right;
//左子树到头了,此刻的subRL就是右子树里最左边的节点
while (subRL->_left)
{
subRL = subRL->_left;
}
_node = subRL;
}
else//代表当前这个子树访问完了,左 中 右 找此根的父亲,该父亲的左孩子是此根。
{
Node* cur = _node;
Node* parent = _node->_parent;
while (parent&& parent->_right==cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
bool operator!=(const Self& s)const
{
return _node != s._node;
}
bool operator==(const Self& s) const
{
return _node == s._node;
}
};
封装成map
- 有了第二个模板参数,为什么还要第一个模板参数K呢;因为查找是按K值查找的…
- 迭代器和插入用的都是红黑树的。参考官方文档可知:插入返回的时pair类型,第一个参数是插入结点或值相等结点的迭代器和布尔值。
- 还有一个
[ ]
重载,返回的时pair<k,v>里面V的引用。make_pair(“呵呵哒”,“我C”)–“我C” typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator
;告诉编译器那一长托是个类型,不然编不过去。
template < class K, class V>
class map
{
struct MapKeyOfT //把 K 提取出来
{
const K& operator()(const pair<const K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
//iterator --》 结点的数据类型
pair<iterator, bool> insert(const pair<const K, V>& kv)
{
return _t.Insert(kv);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
return ret.first->second;// iterator.operator->() data:pair<k,v>的地址 -> second
}
private:
RBTree<K, pair<const K, V>, MapKeyOfT> _t;//使用模板显式的声明使用的类型
};
红黑树的改造
- T:set:int,char…;map:pair<int,int>…
template<class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node; ....//T类型的节点
public:
typedef RBTreeIterator<T, T&, T*> iterator; .....
typedef RBTreeIterator<T, const T&, const T*> const_iterator;
iterator begin()
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
//return left;
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
RBTree()
:_root(nullptr)
{}
....
Node* Find(const K& key);
//插入
pair<iterator, bool> Insert(const T& data)
{
if (_root == nullptr)
{
......
return make_pair(iterator(_root), true);
}
Node* parent = nullptr;
Node* cur = _root;
KeyOfT kot; //仿函数使用场景
while (cur)
{
.......
if (kot(cur->_data) < kot(data))
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur), false);
}
}
// 新增节点,颜色是红色,可能破坏规则3,产生连续红色节点
cur = new Node(data);
Node* newnode = cur; //便于返回迭代器...
cur->_col = RED;
........
_root->_col = BLACK;
return make_pair(iterator(newnode), true);
}
封装成set
- 第二个模板参数也传K…
template < class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
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;
};
----//仿函数使用场景..
KeyOfT kot;
while (cur)
{
if (kot(cur->_data) < kot(data))
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data))
{
parent = cur;
cur = cur->_left;
}
....