当前位置: 首页 > news >正文

【C++】map_set 的封装

目录

一. 源码剖析

二. 逐步实现

1. 框架

2. 仿函数取 Key

3. 迭代器

4. const 迭代器

5. map 的 operator[ ]

三. 整体代码

RBTree.h

MySet.h

MyMap.h


以前理解的 set 是 key;map 是 key_value,似乎是 2 棵树,但其实他俩用同一个类模板

一. 源码剖析

set

#include <stl_tree.h>
#include <stl_set.h>
#include <stl_multiset.h>

set 和 map 是一层浅浅的封装,核心都在树里实现

stl_set.h

template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set {
public:typedef Key key_type;typedef Key value_type;
private:typedef rb_tree<key_type, value_type, // <K, K>identity<value_type>, key_compare, Alloc> rep_type;rep_type t;  // red-black tree representing set
}

stl_map.h

template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map {
public:typedef Key key_type;typedef pair<const Key, T> value_type;
private:typedef rb_tree<key_type, value_type,  // <K, pair<K, V>>select1st<value_type>, key_compare, Alloc> rep_type;rep_type t;  // red-black tree representing map
}

stl_tree.h

struct __rb_tree_node_base
{typedef __rb_tree_color_type color_type;typedef __rb_tree_node_base* base_ptr;color_type color; base_ptr parent;base_ptr left;base_ptr right;
};template <class Value>
struct __rb_tree_node : public __rb_tree_node_base
{typedef __rb_tree_node<Value>* link_type;Value value_field;
};template <class Key, class Value, class KeyOfValue, class Compare,class Alloc = alloc>
class rb_tree {
protected:typedef __rb_tree_node<Value> rb_tree_node;
public:typedef Key key_type;typedef Value value_type;typedef rb_tree_node* link_type;
protected:size_type node_count; // keeps track of size of treelink_type header;  Compare key_compare;
}

link_type 是节点的指针

树的节点里存第二个模板参数 Value ,这个不是真 value
对 map 而言,value_type 传给 Value 的是 pair<K, V>(树的节点存的是 pair<K, V>)
对 set 而言,value_type 传给 Value 的是 K(树的节点存的是 K)

Value 做 __rb_tree_node 的模板参数,决定了树节点 node 里面存什么

二. 逐步实现

1. 框架

MySet.h

#include "RBTree.h"
namespace qtw
{template <class K>class set{private:RBTree<K, K> _t;};
}

MyMap.h

#include "RBTree.h"
namespace qtw
{template <class K, class V>class map{private:RBTree<K, pair<K, V>> _t;};
}

RBTree.h

enum Colour { RED, BLACK };template<class T>
struct RBTreeNode
{RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;Colour _col;T _data;RBTreeNode(const T& data):_data(data),_left(nullptr),_right(nullptr),_parent(nullptr),_col(RED){ }
};template<class K, class T>
class RBTree
{typedef RBTreeNode<T> Node;
public:bool Insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return true;}Node* cur = _root;Node* parent = nullptr;while (cur){if (cur->_data < data){parent = cur;cur = cur->_right;}else if (cur->_data > data){parent = cur;cur = cur->_left;}else{return false;}}// ......}

39 44 行不能用 data 直接比较。set 可以;map 不期望用 pair<>,期望用 pair.first 比较
库里重载了 pair 的比较:first 小或 second 小,但不符合我们的需求

2. 仿函数取 Key

仿函数可以解决,再认识仿函数

在一. 源码剖析可以看到 stl_tree.h 多了个模板参数 KeyOfValue,取出 Value 中的 Key

MySet.h

#include "RBTree.h"
namespace qtw
{template <class K>class set{struct SetKeyOfT // 定义成内部类,可以直接用模板参数 K,V{const K& operator()(const K& key){return key;}};public:bool insert(const K& key){return _t.Insert(key);}private:RBTree<K, K, SetKeyOfT> _t;};
}

MyMap.h

#include "RBTree.h"
namespace qtw
{template <class K, class V>class map{struct MapKeyOfT // 定义成内部类,可以直接用模板参数 K,V{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:bool insert(const pair<K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<K, V>, MapKeyOfT> _t;};
}

RBTree.h

template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<T> Node;
public:Node* Find(const K& key){Node* cur = _root;KeyOfT 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;}bool Insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return true;}Node* cur = _root;Node* parent = nullptr;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 false;}}cur = new Node(data);//cur->_col = RED;if (kot(parent->_data) < kot(data))parent->_right = cur;elseparent->_left = cur;cur->_parent = parent;//......}

仿函数对象调 operator() 取出 T 中的 key
比较交给树里实现,可以用仿函数控制,在一. 源码剖析可以看到 stl_tree.h 第四个模板参数 Compare

3. 迭代器

库里增加了哨兵位的头结点

root == header->parent
header == root->parent

stl_tree.h

iterator begin() { return leftmost(); }
link_type& leftmost() const { return (link_type&) header->left; }
iterator end() { return header; }

我们用空代表 end

迭代器要实现这个:

it = s.begin()
while (it != s.end())
{cout << *it << " ";++it;
}

搜索树的迭代器要中序遍历

++:左 根 右
1. 右不为空,访问右子树的最左节点(最小节点)
2. 右为空,下一个访问的是 孩子是父亲左的父亲(是该节点的祖先)

--:右 根 左
1. 左不为空,访问左子树的最右节点(最大节点)
2. 左为空,下一个访问的是 孩子是父亲右的父亲(是该节点的祖先)

RBTree.h

template<class T>
struct __TreeIterator
{typedef RBTreeNode<T> Node;typedef __TreeIterator<T> Self;Node* _node;__TreeIterator(Node* node):_node(node){ }T& operator*(){return _node->_data;}T* operator->(){return &_node->_data;}bool operator!=(const Self& s){return _node != s._node;}Self& operator--(){if (_node->_left){// 访问左子树的最右节点Node* subRight = _node->_left;while (subRight->_right){subRight = subRight->_right;}_node = subRight;}else{Node* cur = _node;Node* parent = cur->_parent;//while (parent)//{//	if (cur == parent->_right)//	{//		break; // 我是父亲的右,下一个访问父亲(右 根 左)//	}//	else // 我是父亲的左,找孩子是父亲右的那一个//	{//		cur = parent;//		parent = parent->_parent;//	}//}while (parent && cur == parent->_left){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}Self& operator++(){if (_node->_right){// 访问右子树的最左节点Node* subLeft = _node->_right;while (subLeft->_left){subLeft = subLeft->_left;}_node = subLeft;}else{Node* cur = _node;Node* parent = cur->_parent;//while (parent)//{//	if (cur == parent->_left)//	{//		break; // 我是父亲的左,下一个访问父亲(左 根 右)//	}//	else // 我是父亲的右,找孩子是父亲左的那一个//	{//		cur = parent;//		parent = parent->_parent;//	}//}while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}
};template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<T> Node;
public:typedef __TreeIterator<T> iterator;iterator begin(){Node* leftMin = _root;while (leftMin && leftMin->_left) // 有可能空树{leftMin = leftMin->_left;}return iterator(leftMin);}iterator end(){return iterator(nullptr);}Node* Find(const K& key)// ...
}

MySet.h

#include "RBTree.h"
namespace qtw
{template <class K>class set{struct SetKeyOfT // 定义成内部类,可以直接用模板参数 K,V{const K& operator()(const K& key){return key;}};public://typedef RBTree<K, K, SetKeyOfT>::iterator iterator; 错typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const K& key){return _t.Insert(key);}private:RBTree<K, K, SetKeyOfT> _t;};
}

第 16 行错:RBTree<K, K, SetKeyOfT> 是类模板,没被实例化时不生成具体代码,设计没有实例化的具体参数,编译器不敢从类模板里找 iterator;而且内嵌类型、静态也可以用这个语法
加上 typename 是告诉编译器这里是类型,等实例化以后再找 iterator

MyMap.h

#include "RBTree.h"
namespace qtw
{template <class K, class V>class map{struct MapKeyOfT // 定义成内部类,可以直接用模板参数 K,V{const K& operator()(const pair<K, V>& kv){return kv.first;}};public://typedef RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator; 错typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const pair<K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<K, V>, MapKeyOfT> _t;};
}

Test.cpp

#include"MyMap.h"
#include"MySet.h"int main()
{qtw::map<int, int> m;m.insert(make_pair(1, 1));m.insert(make_pair(3, 3));m.insert(make_pair(2, 2));qtw::map<int, int>::iterator mit = m.begin();while (mit != m.end()){//cout << *mit << " "; 错//调operator*,返回T类型的_data,是pair,pair不支持流插入//迭代器模拟自定义类型指针,用operator->cout << mit->first << ":" << mit->second << endl;++mit;}cout << endl;for (const auto& kv : m){cout << kv.first << ":" << kv.second << endl;}cout << endl;qtw::set<int> s;s.insert(5);s.insert(2);s.insert(2);s.insert(12);s.insert(22);s.insert(332);s.insert(7);qtw::set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;for (const auto& e : s){cout << e << " ";}cout << endl;return 0;
}

还有问题:set 本不允许修改;map 仅允许 V 修改;重载 operator[ ] 要改 insert 的返回值

4. const 迭代器

先把树的 const 迭代器搞好,才能搞 set_map 的 const 迭代器

RBTree.h

template<class T, class Ptr, class Ref>
struct __TreeIterator
{typedef RBTreeNode<T> Node;typedef __TreeIterator<T, Ptr, Ref> Self;Node* _node;__TreeIterator(Node* node):_node(node){ }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;}Self& operator--(){if (_node->_left){// 访问左子树的最右节点Node* subRight = _node->_left;while (subRight->_right){subRight = subRight->_right;}_node = subRight;}else{Node* cur = _node;Node* parent = cur->_parent;//while (parent)//{//	if (cur == parent->_right)//	{//		break; // 我是父亲的右,下一个访问父亲(右 根 左)//	}//	else // 我是父亲的左,找孩子是父亲右的那一个//	{//		cur = parent;//		parent = parent->_parent;//	}//}while (parent && cur == parent->_left){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}Self& operator++(){if (_node->_right){// 访问右子树的最左节点Node* subLeft = _node->_right;while (subLeft->_left){subLeft = subLeft->_left;}_node = subLeft;}else{Node* cur = _node;Node* parent = cur->_parent;//while (parent)//{//	if (cur == parent->_left)//	{//		break; // 我是父亲的左,下一个访问父亲(左 根 右)//	}//	else // 我是父亲的右,找孩子是父亲左的那一个//	{//		cur = parent;//		parent = parent->_parent;//	}//}while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}
};template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<T> Node;
public:typedef __TreeIterator<T, T*, T&> iterator;typedef __TreeIterator<T, const T*, const T&> const_iterator;iterator begin(){Node* leftMin = _root;while (leftMin && leftMin->_left) // 有可能空树{leftMin = leftMin->_left;}return iterator(leftMin);}iterator end(){return iterator(nullptr);}const_iterator begin() const{Node* leftMin = _root;while (leftMin && leftMin->_left) // 有可能空树{leftMin = leftMin->_left;}return const_iterator(leftMin);}const_iterator end() const{return const_iterator(nullptr);}Node* Find(const K& key)// ......
}

MySet.h

#include "RBTree.h"
namespace qtw
{template <class K>class set{struct SetKeyOfT // 定义成内部类,可以直接用模板参数 K,V{const K& operator()(const K& key){return key;}};public://typedef RBTree<K, K, SetKeyOfT>::iterator iterator; 错typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;iterator begin() const{return _t.begin();}iterator end() const{return _t.end();}bool insert(const K& key){return _t.Insert(key);}private:RBTree<K, K, SetKeyOfT> _t;};
}

MyMap.h

#include "RBTree.h"
namespace qtw
{template <class K, class V>class map{struct MapKeyOfT // 定义成内部类,可以直接用模板参数 K,V{const K& operator()(const pair<K, V>& kv){return kv.first;}};public://typedef RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator; 错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();}bool insert(const pair<K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<const K, V>, MapKeyOfT> _t;};
}

5. map 的 operator[ ]

RBTree.h

template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<T> Node;
public:typedef __TreeIterator<T, T*, T&> iterator;typedef __TreeIterator<T, const T*, const T&> const_iterator;// ......pair<iterator, bool> Insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return make_pair(iterator(_root), true);}Node* cur = _root;Node* parent = nullptr;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);}}cur = new Node(data);Node* newnode = cur;//cur->_col = RED;if (kot(parent->_data) < kot(data))parent->_right = cur;elseparent->_left = cur;cur->_parent = parent;// 如果cur是根、cur父亲是黑:直接完事// cur父亲是红:进来while (parent && parent->_col == RED){// cur一定有爷,且爷为黑Node* grandfather = parent->_parent;if (grandfather->_left == parent){Node* uncle = grandfather->_right;// uncle存在,且为红:变色,继续更新if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else // uncle不存在,或存在且为黑{if (parent->_left == cur){//     g//   p// cRotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{//     g//   p//     cRotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}}else // grandfather->_right == parent{Node* uncle = grandfather->_left;// uncle存在,且为红:变色,继续更新if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else // uncle不存在,或存在且为黑{if (parent->_right == cur){// g//   p//     cRotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g//   p// cRotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}}}_root->_col = BLACK; // 暴力处理return make_pair(iterator(newnode), true);}};

MyMap.h

V& operator[](const K& key) { }pair<iterator, bool> insert(const pair<K, V>& kv)
{return _t.Insert(kv);
}

MySet.h

报错:“return”: 无法从“std::pair<__TreeIterator<T,T *,T &>,bool>”转换为“std::pair<__TreeIterator<T,const T *,const T &>,bool>”

_t 是普通对象,调 Insert 返回普通迭代器;但红色的 iterator 是 const_iterator


看看库里是怎么搞的

stl_set.h

第 2 行黄色的是普通迭代器,第 3 行绿色的是 const 迭代器

照猫画虎

MySet.h

_t 是树的普通对象,调 Insert 返回树的普通迭代器;但 set 是 const 迭代器,过不不去
单独用普通的树的迭代器对象接收,再这个普通迭代器对象构造 const 迭代器对象
因为 const 迭代器支持了一个构造:18 行

stl_tree.h

第 11 行的 iterator:不管是普通/const 迭代器,这个 iterator 都是普通迭代器

当这个类被实例化成 const 迭代器时,第 18 行的函数是一个构造,支持普通迭代器构造 const 迭代器
__rb_tree_iterator 是 const 迭代器,参数是 iterator 普通迭代器

当这个类被实例化成普通迭代器时,第 18 行的函数是一个拷贝构造


RBTree.h

template<class T, class Ptr, class Ref>
struct __TreeIterator
{typedef RBTreeNode<T> Node;typedef __TreeIterator<T, Ptr, Ref> Self;typedef __TreeIterator<T, T*, T&> Iterator; // 一直是普通迭代器Node* _node;__TreeIterator(const Iterator& it):_node(it._node){ }// ......
}

MyMap.h

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);
}

三. 整体代码

RBTree.h

enum Colour { RED, BLACK };template<class T>
struct RBTreeNode
{RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;Colour _col;T _data;RBTreeNode(const T& data):_data(data),_left(nullptr),_right(nullptr),_parent(nullptr),_col(RED){ }
};template<class T, class Ptr, class Ref>
struct __TreeIterator
{typedef RBTreeNode<T> Node;typedef __TreeIterator<T, Ptr, Ref> Self;typedef __TreeIterator<T, T*, T&> Iterator; // 一直是普通迭代器Node* _node;__TreeIterator(const Iterator& it):_node(it._node){ }__TreeIterator(Node* node):_node(node){ }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;}Self& operator--(){if (_node->_left){// 访问左子树的最右节点Node* subRight = _node->_left;while (subRight->_right){subRight = subRight->_right;}_node = subRight;}else{Node* cur = _node;Node* parent = cur->_parent;//while (parent)//{//	if (cur == parent->_right)//	{//		break; // 我是父亲的右,下一个访问父亲(右 根 左)//	}//	else // 我是父亲的左,找孩子是父亲右的那一个//	{//		cur = parent;//		parent = parent->_parent;//	}//}while (parent && cur == parent->_left){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;}Self& operator++(){if (_node->_right){// 访问右子树的最左节点Node* subLeft = _node->_right;while (subLeft->_left){subLeft = subLeft->_left;}_node = subLeft;}else{Node* cur = _node;Node* parent = cur->_parent;//while (parent)//{//	if (cur == parent->_left)//	{//		break; // 我是父亲的左,下一个访问父亲(左 根 右)//	}//	else // 我是父亲的右,找孩子是父亲左的那一个//	{//		cur = parent;//		parent = parent->_parent;//	}//}while (parent && cur == parent->_right){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;}
};template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<T> Node;
public:typedef __TreeIterator<T, T*, T&> iterator;typedef __TreeIterator<T, const T*, const T&> const_iterator;iterator begin(){Node* leftMin = _root;while (leftMin && leftMin->_left) // 有可能空树{leftMin = leftMin->_left;}return iterator(leftMin);}iterator end(){return iterator(nullptr);}const_iterator begin() const{Node* leftMin = _root;while (leftMin && leftMin->_left) // 有可能空树{leftMin = leftMin->_left;}return const_iterator(leftMin);}const_iterator end() const{return const_iterator(nullptr); // 我们用空代表end}Node* Find(const K& key){Node* cur = _root;KeyOfT 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 T& data){if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return make_pair(iterator(_root), true);}Node* cur = _root;Node* parent = nullptr;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);}}cur = new Node(data);Node* newnode = cur;//cur->_col = RED;if (kot(parent->_data) < kot(data))parent->_right = cur;elseparent->_left = cur;cur->_parent = parent;// 如果cur是根、cur父亲是黑:直接完事// cur父亲是红:进来while (parent && parent->_col == RED){// cur一定有爷,且爷为黑Node* grandfather = parent->_parent;if (grandfather->_left == parent){Node* uncle = grandfather->_right;// uncle存在,且为红:变色,继续更新if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else // uncle不存在,或存在且为黑{if (parent->_left == cur){//     g//   p// cRotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{//     g//   p//     cRotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}}else // grandfather->_right == parent{Node* uncle = grandfather->_left;// uncle存在,且为红:变色,继续更新if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else // uncle不存在,或存在且为黑{if (parent->_right == cur){// g//   p//     cRotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g//   p// cRotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}}}_root->_col = BLACK; // 暴力处理return make_pair(iterator(newnode), true);}void RotateL(Node* parent){Node* cur = parent->_right;Node* curleft = cur->_left;Node* ppnode = parent->_parent;// 2个核心步骤parent->_right = curleft;cur->_left = parent;if (curleft) // 调整curleft父亲节点的指向{curleft->_parent = parent;}parent->_parent = cur; //调整parent父亲节点的指向//cur->_parent = ppnode; 错//调整cur父亲节点的指向if (_root == parent){_root = cur;cur->_parent = nullptr;}else{if (ppnode->_left == parent)ppnode->_left = cur;elseppnode->_right = cur;cur->_parent = ppnode;}}void RotateR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;Node* ppnode = parent->_parent;// 2个核心步骤parent->_left = curright;cur->_right = parent;parent->_parent = cur; // 调整parent父亲节点的指向if (curright) // 调整curright父亲节点的指向{curright->_parent = parent;}//cur->_parent = ppnode; 错// 调整cur父亲节点的指向if (_root == parent){_root = cur;cur->_parent = nullptr;}else{if (ppnode->_right == parent)ppnode->_right = cur;elseppnode->_left = cur;cur->_parent = ppnode;}}bool CheckColor(Node* root, int blacknum, int benchnark){if (root == nullptr){if (benchnark != blacknum)return false;return true;}if (root->_col == BLACK)blacknum++;if (root->_col == RED && root->_parent && root->_parent->_col == RED){cout << root->_kv.first << "出现连续红色节点" << endl;return false;}return CheckColor(root->_left, blacknum, benchnark) && CheckColor(root->_right, blacknum, benchnark);}bool IsBalance(){return IsBalance(_root);}bool IsBalance(Node* root){if (root == nullptr)return true;if (root->_col != BLACK)return false;// 基准值int benchnark = 0;Node* cur = _root;while (cur){if (cur->_col == BLACK)++benchnark;cur = cur->_left;}return CheckColor(root, 0, benchnark);}private:Node* _root = nullptr;
};

MySet.h

#include "RBTree.h"
namespace qtw
{template <class K>class set{struct SetKeyOfT // 定义成内部类,可以直接用模板参数 K,V{const K& operator()(const K& key){return key;}};public://typedef RBTree<K, K, SetKeyOfT>::iterator iterator; 错typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;iterator begin() const{return _t.begin();}iterator end() const{return _t.end();}// iterator RBTree::const_iteratorpair<iterator, bool> insert(const K& key){// pair<RBTree::iterator, bool>pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);return pair<iterator, bool>(ret.first, ret.second);}private:RBTree<K, K, SetKeyOfT> _t;};
}

MyMap.h

#include "RBTree.h"
namespace qtw
{template <class K, class V>class map{struct MapKeyOfT // 定义成内部类,可以直接用模板参数 K,V{const K& operator()(const pair<K, V>& kv){return kv.first;}};public://typedef RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator; 错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;};
}

本篇的分享就到这里了,感谢观看,如果对你有帮助,别忘了点赞+收藏+关注
小编会以自己学习过程中遇到的问题为素材,持续为您推送文章

http://www.dtcms.com/a/605923.html

相关文章:

  • 效益成本原则网站建设如何在网站申请做co
  • 支付网站开发怎么做账微信wordpress
  • Windows下安装Linux子系统Ubuntu
  • 做外贸营销型网站瑞安市住房和城乡规划建设局网站
  • STM32外设学习-串口数据包笔记-(数据包的了解)
  • 3ds Max文件压缩攻略
  • 合肥网站建设q479185700棒有没有做生物科技相关的网站
  • 响应式网站内容布局吉林网站模板
  • 制约楼宇自动化控制系统应用的两大因素:需求匹配与落地能力
  • 反编译易语言 | 解析易语言反编译技术与实践应用
  • 大全!桥梁结构健康实时自动化监测预警——测量设备讲解+架构
  • 快站免费网站建设哪家好网站前面的logo标志
  • 【期末网页设计作业】HTML+CSS+JS 美食分享主题网站设计与实现(附源码)
  • 修复Flyme移植BUG
  • asp 网站管理系统品牌策略有哪些
  • 网站订票策划方案建筑交流平台
  • Python可以爬取哪些公开金融数据
  • 2025年微软MOS认证考试备考计划
  • 微软Office下线“重用幻灯片”功能,WPS反向升级:AI让旧功能焕新生
  • seo优化网站推广专员招聘富德生命人寿保险公司官方网站
  • 济南 营销型网站建设北京动画视频制作公司
  • 智能指针简介
  • 从零实现轻量级C++ Web框架:SimpleHttpServer入门指南
  • 怎样确保CMS系统与现有设备的兼容?
  • 桓台县网站建设wordpress加输入框
  • 今日行情明日机会——20251113
  • 手机访问wordpress网站卡营销型网站有哪些功能
  • 三轴云台之自平衡控制技术
  • 局域网 IP 扫描工具 Ping IP 检查局域网设备
  • 共模电感与差模电感作用有哪些?