map与set封装
封装map和set一般分为6步:
1.封装map与set
2.普通迭代器
3.const 迭代器
4.insert返回值处理
5.map operator【】
6.key不能修改的问题
一.红黑树的改造
map与set的底层是通过红黑树来封装的,但是map与set的结点储存的值不一样,set只需要存储<key,key>,而map中存储的是<key,pair<key,value>>,当我们需要比较结点之间的值时往往是通过value来进行比较,所以我们可以使用一个仿函数来取出map与set中的value值进行比较。
二.红黑树的迭代器
2.1用结点封装迭代器
我们通过红黑树的结点来对迭代器进行实现,首先我们需要三个模板参数T,Ref,Ptr来充当解引用,以及箭头返回值模板。
template<class T, class Ref, class Ptr> struct _TreeIterator {typedef RBTreeNode<T> Node;typedef _TreeIterator<T, Ref, Ptr> Self;Node* _node;Node* _root;_TreeIterator(Node* node, Node* root):_node(node),_root(root){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}Self& operator++(){if (_node->_right){_node = _node->_right;while (_node->_left){_node = _node->_left;}}else{Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}Self& operator--(){if (_node == nullptr){Node* rightmost = _root;while (rightmost && rightmost->_right){rightmost = rightmost->_right;}_node = rightmost;}else if (_node->_left){_node = _node->_left;while (_node && _node->_right){_node = _node->_right;}}else{Node* cur = _node;Node* parent = _node->_parent;while (parent && cur == parent->_left){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;} };
我们重载运算符*和->返回结点的data值。
迭代器遍历++时,原先的树是按照大的在右小的在左的大小进行排序,所以++时,若结点右子树存在,先遍历到第一个右结点(保证了比当前结点的值大),再向左遍历到空结点(保证了是比当前结点大的最小结点值)。若右结点不存在,且当前结点在右子树,就遍历到当前右子树的根结点,返回当前根结点的父结点即为最终值。
红色为起始点,蓝色为最终点,当右结点不为空时的情况
红色为起始结点,蓝色为最终结点,当右结点为空时的情况。
2.2迭代器实现
Iterator Begin()
{Node* minleft = _root;while (minleft && minleft->_left){minleft = minleft->_left;}return Iterator(minleft, _root);
}Iterator End()
{return Iterator(nullptr, _root);
}Const_Iterator Begin() const
{Node* minleft = _root;while (minleft && minleft->_left){minleft = minleft->_left;}return Const_Iterator(minleft, _root);
}Const_Iterator End() const
{return Const_Iterator(nullptr, _root);
}
迭代器使用中序遍历的方式执行,begin从最左端开始
2.3map与set迭代器
set迭代器
typedef typename RBTree<K, const K, SetKetOft>::Iterator iterator;
typedef typename RBTree<K, const K, SetKetOft>::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();
}
_t为红黑树结构
map迭代器
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();
}
三.insert返回值
3.1insert返回值的用处
在map的operator【】中可以看到,他的返回值是通过insert来实现的,这就决定了insert的返回值必须是一个pair<iterator,bool> ,插入一个结点若key已经存在就返回false,若key不存在就返回迭代器以及true。其中在比较两者data数时需要套上一层仿函数取出pair中的值进行比较,保证pair不会走默认比较。
pair<Iterator,bool> Insert(const T& data)
{if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return { Iterator(_root,_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 { 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;}cur->_parent = parent;while (parent && parent->_col == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){// g// p uNode* uncle = grandfather->_right;// 叔叔存在且为红if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLgrandfather->_col = RED;// 继续往上处理cur = grandfather;parent = cur->_parent;}else{// 叔叔不存在或者存在且为黑// g// p u//cif (cur == parent->_left){RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g// p u// cRotateL(parent);RotateR(grandfather);grandfather->_col = RED;cur->_col = BLACK;}break;}}else{ // g// u pNode* uncle = grandfather->_left;// 叔叔存在且为红,-》变色即可if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLgrandfather->_col = RED;// 继续往上处理cur = grandfather;parent = cur->_parent;}else // 叔叔不存在,或者存在且为黑{// 情况二:叔叔不存在或者存在且// 旋转+变色// g// u p// cif (cur == parent->_right){RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g// u p// cRotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}}_root->_col = BLACK;return { Iterator(newnode,_root),true };
}
希望各位大佬多多支持!!!