前言
map和set的底层都是由红黑树构成,但是map是kv模型,set是k模型。如何用一颗子树来同时封装map和set,还有怎么实现map/set的迭代器是这节重点
map和set的模板参数
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t;
struct SetKeyOfT
{
const K& operator()(const K& k)
{
return k;
}
};
private:
RBTree<K, K, SetKeyOfT> _t;
template<class K, class T, class KeyOfT>
我们通过在红黑树模板中增加一个KeyOfT参数,通过map和set的模板来识别是
map还是set
这样后面的数据就要通过KeyOfT形成的对象来比较大小了
如·:查找函数
//查找函数
iterator Find(const K& key)
{
KeyOfT kot;
Node* cur = _root;
while (cur)
{
if (key < kot(cur->_data)) //key值小于该结点的值
{
cur = cur->_left; //在该结点的左子树当中查找
}
else if (key > kot(cur->_data)) //key值大于该结点的值
{
cur = cur->_right; //在该结点的右子树当中查找
}
else //找到了目标结点
{
return iterator(cur); //返回该结点
}
}
return end(); //查找失败
}
迭代器
struct _TreeIterator
{
typedef RBTreeNode<T> Node;
typedef _TreeIterator<T,Ptr,Ref> Self;
typedef _TreeIterator<T, T*, T&> iterator;
};
//构造函数
__TreeIterator(Node* node)
:_node(node) //根据所给结点指针构造一个正向迭代器
{}
++运算符重载
1,右子树不为空,访问右子树的最左节点
2,右子树为空,找到该节点父亲,向上更新
Self& operator++()
{
if (_node->_right)
{
Node* min = _node;
while (min)
{
min = min->_left;
}
_node = min;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && parent->_right == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
--运算符重载
Self& operator--()
{
if (_node->_left)
{
Node* max = _node->_left;
while (max->_right)
{
max=max->_right
}
_node = max;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
if (parent&&cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
迭代器总代码
template<class T,class Ref,class Ptr>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T,Ref, Ptr> Self;
Node* _node;
RBTreeIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()
{
if (_node->_right)
{
Node* min = _node;
while (min)
{
min = min->_left;
}
_node = min;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && parent->_right == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator==(const Self& s) const
{
return _node == s._node;
}
Self& operator--()
{
if (_node->_left)
{
Node* max = _node->_left;
while (max->_right)
{
max=max->_right
}
_node = max;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
if (parent&&cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
};
RBTree代码实现(重点更改部分)
begin()和end()
typedef RBTreeIterator<T, T&, T*> iterator;
iterator begin()
{
Node* min = _root;
while (min&&min->_left)
{
min = min->_left;
}
return iterator(min);
}
iterator end()
{
return iterator(nullptr);
}
构造函数/析构函数
RBTree()
:_root(nullptr)
{}
~RBTree()
{
Destory(root);
_root = nullptr;
}
void Destory(Node* root)
{
if (root == nullptr)
{
return;
}
Destory(root->_left);
Destory(root->_right);
delete root;
}
析构函数是递归进行删除的
拷贝构造/赋值重载
RBTree<K, T, KeyOfT>& operator=(RBTree<K, T, KeyOfT> t)
{
swap(_root, t._root);
return *this;
}
RBTRee(const RBTree<K, T, KeyOfT>& t)
{
_root = Copy(t._root);
}
void* Copy(Node* root)
{
if (root == nullptr)
{
return nullptr;
}
Node* newroot = new Node(*root);
newroot->_col = root->_col;
newroot->_left = Copy(root->_left);
newroot->_right = Copy(root->_right);
if (newroot->_left)
{
newroot->_left->_parent = newroot;
}
if (newroot->_right)
{
newroot->_right->_parent = newroot;
}
return newroot;
}
赋值重载利用现代写法
拷贝构造是递归进行拷贝的,由于只拷贝了节点,所以还要自己手动去链接父节点
插入函数的修改
插入函数修改成
pair<iterator,bool> Insert(const T& data)
返回值为
return make_pair(iterator(newnode), true);
、因为map中【】的本质就是调用insert函数,而【】在map中有多种功能:1:如果存在,返回value值2:如果不存在,则插入新节点
map/set都返回pair结构,其中map返回pair中的k值,set返回k值
set类
#pragma once
#include"RBTree.h"
namespace muyu
{
template<class K>
class set
{
struct SetofT
{
const K& operator()(const K& data)
{
return data;
}
};
public:
typedef typename RBTree<K, K, SetofT>::const_iterator iterator;
typedef typename RBTree<K, K, SetofT>::const_iterator const_iterator;
public:
pair<iterator, bool>& insert(const K& data)
{
pair<RBTree<K, K, SetofT>::iterator, bool> tem = _t.Insert(data);
pair<iterator, bool> res = tem;
return res;
}
iterator begin()const
{
return _t.begin();
}
iterator end()const
{
return _t.end();
}
iterator find(const K& key)
{
return _t.find(key);
}
private:
RBTree<K, K, SetofT> _t;
};
}
map类
#pragma once
#include"RBTree.h"
namespace muyu
{
template<class K, class V>
class map
{
struct MapofT
{
const K& operator()(const pair<K, V>& data)
{
return data.first;
}
};
public:
typedef typename RBTree<K, pair<const K, V>, MapofT>::iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapofT>::const_iterator const_iterator;
public:
pair<iterator, bool> insert(const pair<K, V>& data)
{
return _t.Insert(data);
}
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
const_iterator begin()const
{
return _t.begin();
}
iterator find(const K& key)
{
return _t.find(key);
}
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;
}
private:
RBTree<K, pair<const K, V>, MapofT> _t;
};
}