回顾:之前我们一起学习了map,set,multimap,multiset的接口和相关介绍map和se详细介绍
还实现了AVL树以及RB树,旋转,旋转+变色相信大家已经很熟悉啦手撕AVL和红黑树
本文将带大家一起封装map和set
目录
1.找到方向
2.迭代器最重要的部分
3.set迭代器和map迭代器
4.我的实现
5.源码
首先 我们在实现之前要了解库里面实现的逻辑是什么
也就是对于set,红黑树的节点模板参数只有K,对于map,红黑树节点的模版参数是pair
第一个模板参数为了拿到单独的K类型(相当于索引) 因为find,erase这些接口函数的参数是K
第二个模版参数决定了树的节点里面存什么——K or KV(索引到的结果)
所以我们直接把第二个模板参数改成T,对于set T就是K,对于map T就是pair
begin应该在树中序的第一个,也就是左子树的最后一个节点
end这里我们为了简单 就给成nullptr 但是库里面使用哨兵头节点
库里面的end:对end()位置的迭代器进行--操作,必须要能找最后一个元素,最好的方式是将end()放在头结点的位置
迭代器的++怎么操作?
Self& operator++() {
if (_node->_right) {
//1.右不是空 下一个就是右子树的最左节点
node* subL = _node->_right;
while (subL->_left) {
subL = subL->_left;
}
_node = subL;
}
else {
//2.右为空 当前子树完了 沿着到根的路径 找孩子是父亲左的那个祖先
node* cur = _node;
node* parent = cur->_parent;
while (parent && cur == parent->_right) {
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
++要根据中序 左——根——右
看右子树是不是空 如果是说明当前右子树的根 这一支走完了
要找到这一支的根
只要用一个parent前驱保存一下
--当然是相反的操作
Self& operator--() {
if (_node->_left) {
//1.左不是空 下一个就是左子树的最右节点
node* subR = _node->_left;
while (subR->_right) {
subR = subR->_right;
}
_node = subR;
}
else {
//2.左为空 找孩子是父亲的右的那个祖先
node* cur = _node;
node* parent = cur->_parent;
while (parent && cur == parent->_left) {
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
set的K不能修改 但是现在实现的迭代器居然可以修改!!!
看了库之后发现set的普通迭代器都是const实现的
那么我们跟着改一下啦~~
但是这样报错了
_t是一个普通的树 普通对象调用begin返回普通的迭代器
但是在set中我们的普通迭代器都是用const迭代器实现的
所以出现了问题 根本没有从普通迭代器到const迭代器的构造
报错原因:
编译器看到是一个普通迭代器转换成一个const迭代器 认为这里是类型转换
类型转换可以依赖单参数的构造函数
所以他去匹配
这个构造 没办法把一个普通迭代器转化成node类型
这个函数到底实现的拷贝构造还是构造 取决于类模板被实例化成什么
因为被实例化成const迭代器的时候 传入的就是const& const* 也就是Ref接受了const& Ptr接受了const*
在set中 类模板中iterator就是被实例化成const迭代器 所以就可以实现从普通迭代器到const迭代器的构造
反观map,应该是k不能改 v可以修改
仓库里有代码
RBTree.h
#pragma once
#include "标头.h"
enum Colour {
RED,
BLACK,
};
template
struct RBNode {
RBNode* _left;
RBNode* _right;
RBNode* _parent;
T _data;
Colour _col;
RBNode(const T& data)
:_left(nullptr), _right(nullptr)
, _parent(nullptr),_col(RED)
,_data(data)
{}
};
template
struct __RBTreeIterator {
typedef RBNode node;
typedef __RBTreeIterator Self;
node* _node;
__RBTreeIterator(node* node)
:_node(node)
{}
__RBTreeIterator(const __RBTreeIterator& it) //注意这个不是拷贝构造 相当于传入普通迭代器最后返回
:_node(it._node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->() {
return &_node->_data;
}
bool operator!=(const Self& s) {
return _node != s._node;
}
Self& operator++() {
if (_node->_right) {
//1.右不是空 下一个就是右子树的最左节点
node* subL = _node->_right;
while (subL->_left) {
subL = subL->_left;
}
_node = subL;
}
else {
//2.右为空 当前子树完了 沿着到根的路径 找孩子是父亲左的那个祖先
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->_left) {
//1.左不是空 下一个就是左子树的最右节点
node* subR = _node->_left;
while (subR->_right) {
subR = subR->_right;
}
_node = subR;
}
else {
//2.左为空 找孩子是父亲的右的那个祖先
node* cur = _node;
node* parent = cur->_parent;
while (parent && cur == parent->_left) {
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
};
template
class RBTree
{
public:
typedef RBNode node;
~RBTree()
{
_Destroy(_root);
_root = nullptr;
}
public:
typedef __RBTreeIterator iterator;
typedef __RBTreeIterator const_iterator;
iterator begin() {
node* cur = _root;
while (cur && cur->_left) {
cur = cur->_left;
}
return iterator(cur);
}
iterator end() {
return iterator(nullptr);
}
const iterator begin() const {
node* cur = _root;
while (cur && cur->_left) {
cur = cur->_left;
}
return iterator(cur);
}
const iterator end() const {
return iterator(nullptr);
}
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;
}
void RotateL(node* pre) {
//subR subRL pp
//pre_bf = 2 && cur_bf = 1
//要注意的是subRL可能是空 pre的pre可能是空(此时检索到根节了)
node* subR = pre->_right;
node* subRL = subR->_left;
pre->_right = subRL;
if (subRL) subRL->_parent = pre;
node* pp = pre->_parent;
subR->_left = pre;
pre->_parent = subR;
if (pp == nullptr) {
_root = subR;
_root->_parent = nullptr;
}
else {
if (pp->_left == pre) {
pp->_left = subR;
}
else {
pp->_right = subR;
}
subR->_parent = pp;
}
}
void RotateR(node* pre) {
//subL subLR pp
//pre_bf=-2 cur_bf=-1
node* subL = pre->_left;
node* subLR = subL->_right;
pre->_left = subLR;
if (subLR) subLR->_parent = pre;
node* pp = pre->_parent;
subL->_right = pre;
pre->_parent = subL;
if (pre == _root) {
_root = subL;
_root->_parent = nullptr;
}
else {
if (pp->_left == pre) pp->_left = subL;
else pp->_right = subL;
subL->_parent = pp;
}
}
bool IsBalance() {
if (_root && _root->_col == RED) {
cout << "根节点颜色是红色" << endl;
return false;
}
int benchmark = 0;
node* cur = _root;
while (cur) {
if (cur->_col == BLACK) ++benchmark;
cur = cur->_left;
}
return _Check(_root, 0, benchmark);
}
int Height()
{
return _Height(_root);
}
pair Insert(const T& data)
{
if (_root == nullptr)
{
_root = new node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
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 make_pair(iterator(cur), false);
}
}
cur = new node(data);
node* newnode = cur;
if (kot(parent->_data) > kot(data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
while (parent && parent->_col == RED)
{
node* grandfather = parent->_parent;
if (grandfather->_left == parent)
{
node* uncle = grandfather->_right;
// 情况1:u存在且为红,变色处理,并继续往上处理
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
// 继续往上调整
cur = grandfather;
parent = cur->_parent;
}
else // 情况2+3:u不存在/u存在且为黑,旋转+变色
{
// g
// p u
// c
if (cur == parent->_left)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// g
// p u
// c
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
//parent->_col = RED;
grandfather->_col = RED;
}
break;
}
}
else // (grandfather->_right == parent)
{
// g
// u p
// c
node* uncle = grandfather->_left;
// 情况1:u存在且为红,变色处理,并继续往上处理
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
// 继续往上调整
cur = grandfather;
parent = cur->_parent;
}
else // 情况2+3:u不存在/u存在且为黑,旋转+变色
{
// g
// u p
// c
if (cur == parent->_right)
{
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
else
{
// g
// u p
// c
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return make_pair(iterator(newnode), true);;
}
private:
void _Destroy(node* root)
{
if (root == nullptr)
{
return;
}
_Destroy(root->_left);
_Destroy(root->_right);
delete root;
}
int _Height(node* root)
{
if (root == NULL)
return 0;
int leftH = _Height(root->_left);
int rightH = _Height(root->_right);
return leftH > rightH ? leftH + 1 : rightH + 1;
}
bool _Check(node* root, int blacknum, int benchmark)
{
if (root == nullptr) {
if (benchmark != blacknum) {
cout << "某条路上黑节点数量不等" << endl;
return false;
}
return true;
}
if (root->_col == BLACK) {
++blacknum;
}
if (root->_col == RED && root->_parent && root->_parent->_col==RED) {
cout << "存在连续红色" << endl;
return false;
}
return _Check(root->_left, blacknum, benchmark) && _Check(root->_right, blacknum, benchmark);
}
private:
node* _root=nullptr;
};
map.h
#pragma once
#include "RBTree.h"
namespace wrt {
template
class map{
public:
struct MapKeyofT {
const K& operator()(const pair& kv) {
return kv.first;
}
};
typedef typename RBTree, MapKeyofT>::iterator iterator;
typedef typename RBTree, MapKeyofT>::const_iterator const_iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
V& operator[](const K& key)
{
pair ret=_t.Insert(make_pair(key, V()));
return ret.first->second;
}
pair insert(const pair& kv)
{
return _t.Insert(kv);
}
private:
RBTree,MapKeyofT> _t;
};
void test_map1()
{
map dict;
dict.insert(make_pair("sort", "排序"));
dict.insert(make_pair("string", "字符串"));
dict.insert(make_pair("count", "计数"));
dict.insert(make_pair("string", "字符"));//插入失败
map::iterator it = dict.begin();
while (it != dict.end())
{
cout << it->first << ":" << it->second << endl;
it->first = "sdh";
it->second = "222";
++it;
}
cout << endl;
for (auto& kv : dict)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
void test_map2()
{
string arr[] = { "hello","hello","hi"};
map countMap;
for (auto& e : arr)
{
countMap[e]++;
}
for (auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
}
}
set.h
#pragma once
#include "RBTree.h"
namespace wrt {
template
class set {
struct SetKeyofT {
const K& operator()(const K& key) {
return key;
}
};
public:
//编译器无法识别RBTree是一个静态变量还是一个类型
//类模板里面取RBTree 一定要加上typename
//目的是告诉编译器这是一个类型 等类模板实例化之后再去取这个类型
//由于set不能修改K也就是value 普通迭代器也是用const迭代器实现的
typedef typename RBTree::const_iterator iterator;
typedef typename RBTree::const_iterator const_iterator;
iterator begin()
{
//但是这里有一个编译错误
return _t.begin();
}
iterator end() {
return _t.end();
}
pair insert(const K& key)
{
return _t.Insert(key);
}
private:
RBTree _t;
};
void test_set() {
set s;
int a[] = {4,1,7,88,5,2,6,4,7,8,2,3,0};
for (auto e : a) {
s.insert(e);
}
set::iterator it= s.begin();
while (it != s.end()) {
cout << *it << " ";
//*it=1;
++it;
}
cout << endl;
}
}
源码在这里