首先看看map对K和V的定义
然后看看set的
可以发现的一点就是源代码中的K/V与我们之前定义的K/V不同,这里的K可以说没什么价值,而V自身就有了我们传统意义上的K/V。
map中成员变量的定义:
set中成员函数的定义:
从typedef的角度上讲,二者的唯一区别就是value_type的不同,且二者的本质只是红黑树模板类中的一个类模板。因此map和set的本质和list中的迭代器用法差不多,实现一个共用类,然后通过模板参数的不同来实现不同的功能。
(简化理解typedef一个模板类就是typedef一个类型,只是这个类型中有模板参数而已)
例:
cpp
template<class K,class V>
class RBtree
{
//..
};
//set和map只是RBtree中的一个类模板
template<class K,class V>
class map
{
typedef RBtree<K, V> __map;
//..
__map _map;
};
template<class K>
class set
{
typedef RBtree<K, K> __set;
//..
__set _set;
};
2.要设计K和V的原因在于map中的find和pop成员函数要用K类型来找而非V类型,说白了就是set中的value没有意义,是为了map而做牺牲的。
3.模拟实现set和map的大框
map:
cpp
template<class K,class V>
class map
{
//const K,因为map中的K不允许修改,但map允许
typedef RBTree<K, pair<const V,K>,mapcom> __map;
private:
__map _map;
};
set:
template<class K>
class set
{
typedef RBTree<K, K> __set;
private:
__set _set;
};
2.然后就是改造一下RBTree
(1)node的改造
cpp
//一个模板参数即可,因为map中传进来的就是pair类型了
template<class T>
struct RBTreeNode
{
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
T _val;
int _col;
RBTreeNode(const T& val)
:_val(val)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{ }
};
(2)insert
//修改一下形参类型即可
typedef RBTreeNode<V> Node;
bool insert(const V& val)
(3)把本来应该用interator实现的成员函数都删掉
4.pair的比较逻辑是先比较first再比较second,但在map中我们只想first进行比较,因此set和map的insert中的比较逻辑并不兼容,因此我们要分别为二者设计一个仿函数
set:
cpp
template<class T>
struct setcom
{
const T& operator()(const T& v)
{
return v;
}
};
template<class K>
class set
{
typedef RBTree<K, K,setcom<K>> __set;
private:
__set _set;
};
map:
cpp
template<class K,class V>
struct mapcom
{
const K& opertor()(const pair<K,V>& v)
{
return v.first;
}
};
template<class K,class V>
class map
{
//const K,因为map中的K不允许修改,但map允许
typedef RBTree<K, pair<const V,K>,mapcom<K,V>> __map;
private:
__map _map;
};
RBtree中:
cpp
多一个传仿函数的模板参数
template<class K, class V,class typecom>
class RBTree
//insert中的比较逻辑的举例
if (com(cur->_val) < com(val))
{
parent = cur;
cur = cur->_right;
}
else if (com(cur->_val) > com(val))
{
parent = cur;
cur = cur->_left;
}
5.在set和map中调用函数的方式就是套壳
例set中:
bool insert(const K& key)
{
return _set.insert(key);
}
6.set和map的itertator
set和map的iterator就是RBtree对应模板类型内部的原生迭代器。
原因也很简单:set和map就是给RBtree中的模板类,其内部结构就是红黑树,因此是包装RBtree的迭代器也很合理。
(1)iterator的遍历是按中序遍历,因此begin()返回的是中序的第一个结点。end()返回nullptr(没有头结点时)
(2)大框还是指针+重载
(3)遍历逻辑
{
1.当前结点右子树不为空就去找右子树的最左结点(说明该树未遍历完)
2.当前结点右子树为空就去找祖先(当前树已遍历完)
}
RBtree中的iterator代码大框
cpp
template<class T, class ref, class ptr>
struct RBTreeItreator
{
typedef RBTreeNode<T> Node;
typedef RBTreeItreator<T, ref, ptr> self;
//_root是用于处理特殊情况的
RBTreeItreator(Node* node,Node*_root)
:_node(node)
,_root(_root)
{ }
//...(下面补充iterator的重载)
Node* _node;
Node* _root;
};
RBtree的begin和end实现:
cpp
Iterator begin()
{
Node* cur = _root;
while (cur&&cur->_left)
{
cur = cur->_left;
}
return Iterator(cur, _root);
}
Iterator end()
{
return Iterator(nullptr, _root);
}
RBtree的iterator的++重载
cpp
self& operator++()
{
//将_node更新到右子树的最左结点
if (_node->_right)
{
Node* cur = _node->_right;
while (cur->_left)
{
cur = cur->_left;
}
_node = cur;
}
else
{
Node* parent = _node->_parent;
Node* cur = _node;
//parent==nullptr说明cur到根了
//cur != parent->_right说明目前这颗树未遍历完
while (parent && cur==parent->_right)
{
cur = parent;
parent = parent->_parent;
}
//此处的_node要么是遍历完的nullptr,要么是下一个要遍历的根节点
_node = parent;
}
return *this;
}
由于我的能力有限,因此只能改变写的方式了。
--重载
这里想说明的就是_root成员的意义,当想iterator从end()开始的反向遍历,就需要对_node==nullptr的情况进行特殊处理,让其在这中情况下走到最右结点处。
cpp
Self operator--()
{
if (_node == nullptr) // --end()
{
// --end(),特殊处理,走到中序最后一个结点,整棵树的最右结点
Node* rightMost = _root;
while (rightMost && rightMost->_right)
{
rightMost = rightMost->_right;
}
_node = rightMost;
}
else if (_node->_left)
{
// 左子树不为空,中序左子树最后一个
Node* rightMost = _node->_left;
while (rightMost->_right)
{
rightMost = rightMost->_right;
}
_node = rightMost;
}
else
{
// 孩子是父亲右的那个祖先
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
RBTree中iterator的解引用重载
cpp
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
这样重载有一个问题,*map时可以直接修改first(key)使树结构出问题,此时在map中的传模板参数时就要给pair中的K加上const。
cpp
//务必注意iterator的类型也要跟着修改
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::Iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::ConstIterator const_iterator;
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
哨兵位的意义:

指向树的最右和最左,其parent指向head,好处就是不用判空和begin(),end()的获取简单,坏处就是要一直维护。
map中的[]重载
cpp
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert({ key, V() });
return ret.first->second;
}
此时就要修改一下insert的返回值了。
cpp
pair<Iterator, bool> Insert(const T& data)
{
//判空
if (_root == nullptr);
KeyOfT kot;
Node* parent = nullptr;
Node* cur = _root;
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 { Iterator(cur, _root), false };
}
}
cur = new Node(data);
Node* newnode = cur;
cur->_col = RED;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
//..后面的处理都删了
return { Iterator(newnode, _root), true };
}
后面写出这次的重要代码以便我以后复习:
map:
cpp
template<class K, class V>
class map
{
//仿函数可以为内部类
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
//const K使解引用时K不可被修改
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::Iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::ConstIterator 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();
}
pair<iterator, bool> insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
V& operator[](const K& key)
{
//注意V()的默认构造
pair<iterator, bool> ret = insert({ key, V() });
//两层pair
return ret.first->second;
}
private:
//K的意义可以说没有,V的类型才重要
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
set:
cpp
template<class K>
//没有[]重载
class set
{
//可以说这里的仿函数就是为了map才有的
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;
typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator 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();
}
pair<iterator, bool> insert(const K& key)
{
return _t.Insert(key);
}
private:
//set的K直接就不允许修改
RBTree<K, const K, SetKeyOfT> _t;
};
RBTree:
cpp
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)
{}
};
template<class T, class Ref, class Ptr>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, Ref, Ptr> Self;
Node* _node;
Node* _root;
RBTreeIterator(Node* node, Node* root)
:_node(node)
,_root(root)
{}
Self operator++()
{
if (_node->_right)
{
// 右不为空,中序下一个访问的节点是右子树的最左(最小)节点
Node* min = _node->_right;
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else
{
// 右为空,祖先里面孩子是父亲左的那个祖先
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
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;
}
};
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*> ConstIterator;
ConstIterator Begin() const
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return ConstIterator(cur, _root);
}
ConstIterator End() const
{
return ConstIterator(nullptr, _root);
}
pair<Iterator, bool> Insert(const T& data)
{
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 { Iterator(cur, _root), false };
}
}
cur = new Node(data);
Node* newnode = cur;
cur->_col = RED;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
}
//..
//要注意对iterator的创建与初始化
return { Iterator(cur, _root), true };
}
private:
Node* _root = nullptr;
};
insert返回有iterator的pair,iterator由Node*构造。