文章目录
map模拟实现
由于set/map的底层就是红黑树,因此只需要在set/map中封装一棵红黑树就可以将容器模拟实现出来
总体框架接口展示
```cpp
enum Color{
RED, BLACK};
template<class T>
struct RBTreeNode
{
RBTreeNode(const T& data)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_col(RED)
,_data(data)
{
}
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _col;
T _data;
};
template<class T, class Ref, class Ptr>
struct rbtree_iterator
{
typedef RBTreeNode<T> Node;
typedef rbtree_iterator<T, Ref, Ptr> iterator;
rbtree_iterator(Node* node)
:_node(node)
{
}
iterator operator++();
iterator operator--();
bool operator!=(const iterator& it) {
return _node != it._node; }
Ref operator*() {
return _node->_data; }
Ptr operator->() {
return &_node->_data; }
Node* _node;
};
template<class K, class T, class KeyOfT>
struct RBTree
{
typedef rbtree_iterator<T, T&, T*> iterator;
typedef RBTreeNode<T> Node;
RBTree()
:_root(nullptr)
{
}
~RBTree() {
Destroy(_root); };
RBTree(const RBTree<K, T, KeyOfT>& rb) {
_root = Copy(rb._root) ; }
RBTree& operator=(RBTree tree) {
swap(_root, tree._root); return *this;}
iterator begin();
iterator end();
iterator find(const K& key);
pair<iterator, bool> insert(const T& data);
private:
void Lrotate(Node* cur);
void Rrotate(Node* cur);
void LRrotate(Node* cur);
void RLrotate(Node* cur);
void Destroy(Node* root);
Node* Copy(Node* root);
Node* _root;
};
template<class K>
class my_set
{
public:
//仿函数
struct MapKeyOfT{
const K& operator()(const K& key) {
return key;}
};
typedef typename RBTree<K, K, MapKeyOfT>::iterator iterator;
//迭代器相关接口
iterator begin() {
return _t.begin(); }
iterator end() {
return _t.end(); }
//查找
iterator find(const K& k) {
return _t.find(k);}
//插入
pair<iterator, bool> insert(const K& key) {
return _t.insert(key);};
//交换函数
void swap(my_set& s) {
swap(_t, s._t);}
private:
RBTree<K, K, MapKeyOfT> _t; //成员变量时是一棵搜索树
};
template<class K, class V>
class my_map
{
public:
//防函数
struct MapKeyOfT{
const K& operator()(const pair<K, V>& kv) {
return kv.first;}
};
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
//迭代器相关接口
iterator begin() {
return _t.begin(); }
iterator end() {
return _t.end(); }
//查找
iterator find(const K& k) {
return _t.find(k);}
//插入
pair<iterator, bool> insert(const pair<K, V>& kv) {
return _t.insert(kv);};
//[]运算符重载
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.insert(make_pair(key, V()));
return ret.first->second;
}
//交换函数
void swap(my_map& m) {
swap(_t, m._t);}
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t; //成员变量时是一棵搜索树
};
红黑树框架和接口实现
红黑树结点
enum Color{
RED, BLACK};
template<class T>
struct RBTreeNode
{
RBTreeNode(const T& data)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_col(RED)
,_data(data)
{
}
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _col;
T _data;
};
和上节红黑树的实现相同的结点结构, T类型为结点中存储值数据的类型,在set中是key,在map中是pair<key, value>
红黑树迭代器
template<class T, class Ref, class Ptr>
struct rbtree_iterator
{
typedef RBTreeNode<T> Node;
typedef rbtree_iterator<T, Ref, Ptr> iterator;
rbtree_iterator(Node* node)
:_node(node)
{
}
iterator operator++();
iterator operator--();
bool operator!=(const iterator& it) {
return _node != it._node; }
Ref operator*() {
return _node->_data; }
Ptr operator->() {
return &_node->_data; }
Node* _node; //成员变量
};
通过传入的Ref和Ptr来控制结点的值data是否可以改变,这里主要实现了一些基本的迭代器功能,而迭代器的底层就是一个Node* 指针
operator++
在map和set 的 迭代器遍历中,采用的是中序遍历。那么在遍历过程中可能会出现以下几种情况
1.当cur为nullptr时,返回空迭代器也就是end()
2.当cur存在右节点时 -> 找到cur右子树的最左结点
3.当cur没有右节点时,说明一棵子树的左根右都遍历完毕,需要找到子树根的双亲, 向上遍历此时有两种情况
一、若cur为parent的右节点。说明子树也已经遍历完毕,继续向上,直到cur为parent的左节点,那么此时cur就是新树的新根
二、一直向上直到根结点,cur都是parent的右节点,说明这棵树已经遍历完毕,返回end()
前面两种情况非常简单,这里对情况3的两种情况进行画图分析
情况3(一)
情况3(二)
template<class T, class Ref, class Ptr>
rbtree_iterator<T, Ref, Ptr> rbtree_iterator<T, Ref, Ptr>::operator++()
{
//情况1
Node* cur = _node;
if (cur == nullptr)
{
_node = nullptr;
return *this;
}
//情况2
if (cur->_right)
{
cur = cur->_right;
while (cur->_left)
{
cur = cur->_left;
}
_node = cur;
return *this;
}
//情况三
else
{
Node* parent = cur->_parent;
while (parent && parent->_right == cur)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
return *this;
//在实现情况3的时候我们发现一二两种情况可以公用一份代码,因为二情况达到跟的时候parent刚好为空
}
}
operator–
template<class T, class Ref, class Ptr>
rbtree_iterator<T, Ref, Ptr> rbtree_iterator<T, Ref, Ptr>::operator--()
{
Node* cur = _node;
if (cur == nullptr)
{
return *this;
}
if (_node->_left)
{
cur = _node->_left;
while (cur->_right)
{
cur = cur->_right;
}
_node = cur;
return *this;
}
else
{
Node* parent = cur->_parent;
while (parent && parent->_left == cur)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
return *this;
}
}
具体实现和operator++相近,就是反过来了,可以对照看看代码
operator* 和operator->
Ref operator*() {
return _node->_data; }
Ptr operator->() {
return &_node->_data; }
红黑树
template<class K, class T, class KeyOfT>
struct RBTree
{
typedef rbtree_iterator<T, T&, T*> iterator;
typedef RBTreeNode<T> Node;
//构造函数
RBTree()
:_root(nullptr)
{
}
//析构函数
~RBTree() {
Destroy(_root); };
//拷贝构造
RBTree(const RBTree<K, T, KeyOfT>& rb) {
_root = Copy(rb._root) ; }
//赋值运算符重载
RBTree& operator=(RBTree tree) {
swap(_root, tree._root); return *this;}
//迭代器相关接口
iterator begin();
iterator end();
//查找
iterator find(const K& key);
//插入
pair<iterator, bool> insert(const T& data);
private:
//插入内部旋转使用的函数
void Lrotate(Node* cur);
void Rrotate(Node* cur);
void LRrotate(Node* cur);
void RLrotate(Node* cur);
//析构函数的子函数
void Destroy(Node* root);
//拷贝构造的子函数
Node* Copy(Node* root);
Node* _root;
};
这里使用了泛型的思想,因为map和set都是由这棵树封装的,我们并不知道T存储的到底是哪种数据类型,但是不管是map还是set,我们都只关心key的数值,因为这是我们比较大小构建树的关键,所以构建一个仿函数,通过我们的自己传入类型来得到key。
K是key的值,T是结点存储的数据,可能是K,也可能是pair<K, V>。不管是set还是map都是需要使用key进行比较的,所以我们构建一个仿函数,KeyOfT作用就是若T为pair,取出T.first,若T为key,则直接返回key
构造函数
RBTree()
:_root(nullptr)
{
}
拷贝构造函数
RBTree(const RBTree<K, T, KeyOfT>& rb) {
_root = Copy(rb._root) ; }
template<class K, class T, class KeyOfT>
RBTreeNode<T>* RBTree<K, T, KeyOfT>::Copy(Node* root)
{
if (root == nullptr)
return nullptr;
//创建根节点
Node* newRoot = new Node(root->_data);
//递归copy其左节点
newRoot->_left = Copy(root->_left);
//若左节点存在将其链接
if (newRoot->_left)
newRoot->_left->_parent = newRoot;
//递归copy其右节点
newRoot->_right = Copy(root->_right);
//若右节点存在则进行链接
if (newRoot->_right)
newRoot->_right->_parent = newRoot;
return newRoot;
}
此处设计了Copy子函数,关于子函数我们可以将其状态设置为保护,这样可以更好的体现类与对象的封装,也可以更好的控制递归
operator=
此处采用现代写法,在传参的时候拷贝构造了tree,这时我们交换两棵树的_root,则就将两棵树进行互换,函数结束销毁形参的拷贝,调用析构函数将tree进行清理
RBTree& operator=(RBTree tree) {
swap(_root, tree._root); return *this;}
析构函数
~RBTree() {
Destroy(_root); }
template<class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::Destroy(Node* root)
{
if (root == nullptr)
{
return;
}
else
{
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
}
先递归删除左子树,后删除右树,最后删除根。因为用到了递归,所以使用子函数进行控制
begin() 和 end()
template<class K, class T, class KeyOfT>
typename RBTree<K, T, KeyOfT>::iterator RBTree<K, T, KeyOfT>::begin()
{
Node* min = _root;
while (min && min->_left)
{
min = min->_left;
}
return iterator(min);
}
template<class K, class T, class KeyOfT>
typename RBTree<K, T, KeyOfT>::iterator RBTree<K, T, KeyOfT>::end()
{
return iterator(nullptr);
}
最左结点为begin(),空节点为end,非常简单
Find()函数
template<class K, class T, class KeyOfT>
typename RBTree<K, T, KeyOfT>::iterator RBTree<K, T, KeyOfT>::find(const K& key)
{
KeyOfT kot;
Node* cur = _root;
while (cur)
{
if (key > kot(cur->_data))
{
cur = cur->_right;
}
else if (key < kot(cur->_data))
{
cur = cur->_left;
}
else
{
return iterator(cur);
}
}
return iterator(nullptr);
}
对key进行kot()处理后进行比较,根据和curkey大小比较进行向下处理。这里使用大于小于并不规范,因为取得的值可能是指针等。我们可以新增一个模板参数来控制大于小于运算符,这样可以自行定义operator()来对><=运算符进行控制
insert()函数和旋转函数
这个是上一节的重点,具体实现上一节已经讲过了,只需要简单的改变返回值即可,具体实现会在结尾放出,模拟实现思路可以看上一节
这里放上地址:红黑树insert的模拟实现
map框架
map封装了上面实现的红黑树,其接口都可以通过调用红黑树接口进行实现。其六大默认函数我们并不需要写,因为系统默认生成的默认函数会自动调用自定义类型的默认函数
template<class K, class V>
class my_map
{
public:
//防函数
struct MapKeyOfT{
const K& operator()(const pair<K, V>& kv) {
return kv.first;}
};
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
//迭代器相关接口
iterator begin() {
return _t.begin(); }
iterator end() {
return _t.end(); }
//查找
iterator find(const K& k) {
return _t.find(k);}
//插入
pair<iterator, bool> insert(const pair<K, V>& kv) {
return _t.insert(kv);};
//[]运算符重载
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.insert(make_pair(key, V()));
return ret.first->second;
}
//交换函数
void swap(my_map& m) {
swap(_t, m._t);}
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t; //成员变量时是一棵搜索树
};
我们可以观察到 my_map没有四个默认函数,这是因为my_map的底层是一颗红黑树,是自定义类型,编译器自动生成的默认成员函数会自动调用自定义类型的默认成员函数,所以我们没必要再写一遍,使用编译器生成的就足够了
set模拟实现
set框架
template<class K>
class my_set
{
public:
//仿函数
struct SetKeyOfT{
const K& operator()(const K& key) {
return key;}
};
typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
//迭代器相关接口
iterator begin() {
return _t.begin(); }
iterator end() {
return _t.end(); }
//查找
iterator find(const K& k) {
return _t.find(k);}
//插入
pair<iterator, bool> insert(const K& key) {
return _t.insert(key);};
//交换函数
void swap(my_set& s) {
swap(_t, s._t);}
private:
RBTree<K, K, SetKeyOfT> _t; //成员变量时是一棵搜索树
};
可以发现map和set的差别就是map右两个模板参数,而set只有一个,只要进行部分改动就可以实现set
源码
最后附上源码,可以自行复制查看验证
my_rbtree.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
enum Color{
RED, BLACK};
template<class T>
struct RBTreeNode
{
RBTreeNode(const T& data)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_col(RED)
,_data(data)
{
}
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _col;
T _data;
};
template<class T, class Ref, class Ptr>
struct rbtree_iterator
{
typedef RBTreeNode<T> Node;
typedef rbtree_iterator<T, Ref, Ptr> iterator;
rbtree_iterator(Node* node)
:_node(node)
{
}
iterator operator++();
iterator operator--();
bool operator!=(const iterator& it) {
return _node != it._node; }
Ref operator*() {
return _node->_data; }
Ptr operator->() {
return &_node->_data; }
Node* _node;
};
template<class T, class Ref, class Ptr>
rbtree_iterator<T, Ref, Ptr> rbtree_iterator<T, Ref, Ptr>::operator++()
{
Node* cur = _node;
if (cur == nullptr)
{
_node = nullptr;
return *this;
}
if (cur->_right)
{
cur = cur->_right;
while (cur->_left)
{
cur = cur->_left;
}
_node = cur;
return *this;
}
else
{
Node* parent = cur->_parent;
while (parent && parent->_right == cur)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
return *this;
}
}
template<class T, class Ref, class Ptr>
rbtree_iterator<T, Ref, Ptr> rbtree_iterator<T, Ref, Ptr>::operator--()
{
Node* cur = _node;
if (cur == nullptr)
{
return *this;
}
if (_node->_left)
{
cur = _node->_left;
while (cur->_right)
{
cur = cur->_right;
}
_node = cur;
return *this;
}
else
{
Node* parent = cur->_parent;
while (parent && parent->_left == cur)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
return *this;
}
}
template<class K, class T, class KeyOfT>
struct RBTree
{
typedef rbtree_iterator<T, T&, T*> iterator;
typedef RBTreeNode<T> Node;
RBTree()
:_root(nullptr)
{
}
~RBTree() {
Destroy(_root); };
RBTree(const RBTree<K, T, KeyOfT>& rb) {
_root = Copy(rb._root) ; }
RBTree& operator=(RBTree tree) {
swap(_root, tree._root); return *this;}
iterator begin();
iterator end();
iterator find(const K& key);
pair<iterator, bool> insert(const T& data);
private:
void Lrotate(Node* cur);
void Rrotate(Node* cur);
void LRrotate(Node* cur);
void RLrotate(Node* cur);
void Destroy(Node* root);
Node* Copy(Node* root);
Node* _root;
};
template<class K, class T, class KeyOfT>
RBTreeNode<T>* RBTree<K, T, KeyOfT>::Copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* newRoot = new Node(root->_data);
newRoot->_left = Copy(root->_left);
if (newRoot->_left)
newRoot->_left->_parent = newRoot;
newRoot->_right = Copy(root->_right);
if (newRoot->_right)
newRoot->_right->_parent = newRoot;
return newRoot;
}
template<class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::Destroy(Node* root)
{
if (root == nullptr)
{
return;
}
else
{
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
}
template<class K, class T, class KeyOfT>
typename RBTree<K, T, KeyOfT>::iterator RBTree<K, T, KeyOfT>::begin()
{
Node* min = _root;
while (min && min->_left)
{
min = min->_left;
}
return iterator(min);
}
template<class K, class T, class KeyOfT>
typename RBTree<K, T, KeyOfT>::iterator RBTree<K, T, KeyOfT>::end()
{
return iterator(nullptr);
}
template<class K, class T, class KeyOfT>
typename RBTree<K, T, KeyOfT>::iterator RBTree<K, T, KeyOfT>::find(const K& key)
{
KeyOfT kot;
Node* cur = _root;
while (cur)
{
if (key > kot(cur->_data))
{
cur = cur->_right;
}
else if (key < kot(cur->_data))
{
cur = cur->_left;
}
else
{
return iterator(cur);
}
}
return iterator(nullptr);
}
template<class K, class T, class KeyOfT>
pair<typename RBTree<K, T, KeyOfT>::iterator, bool> RBTree<K, T, KeyOfT>::insert(const T& data)
{
Node* newnode;
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
else
{
KeyOfT kot;
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (kot(data) > kot(cur->_data))
{
parent = cur;
cur = cur->_right;
}
else if (kot(data) < kot(cur->_data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur), false);
}
}
cur = new Node(data);
newnode = cur;
cur->_parent = parent;
if (kot(cur->_data) > kot(parent->_data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
Node* uncle;
if (parent == grandfather->_left)
{
uncle = grandfather->_right;
if (uncle && uncle->_col == RED)
{
uncle->_col = parent->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = grandfather->_parent;
}
else if (uncle && uncle->_col == BLACK)
{
if (parent->_left == cur)
{
Rrotate(parent);
_root->_col = BLACK;
break;
}
else
{
//cur 是 parent的右节点
LRrotate(cur);
_root->_col = BLACK;
break;
}
}
else
{
//uncle 不存在
if (parent->_left == cur)
{
Rrotate(parent);
_root->_col = BLACK;
break;
}
else
{
//cur 是 parent的右节点
LRrotate(cur);
_root->_col = BLACK;
break;
}
}
}
else
{
uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
uncle->_col = parent->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = grandfather->_parent;
}
else if (uncle && uncle->_col == BLACK)
{
if (parent->_right == cur)
{
Lrotate(parent);
break;
}
else
{
//cur 是 parent的左节点
RLrotate(cur);
break;
}
}
else
{
//uncle 不存在
if (parent->_right == cur)
{
Lrotate(parent);
break;
}
else
{
//cur 是 parent的左节点
RLrotate(cur);
break;
}
}
}
}
}
_root->_col = BLACK;
return make_pair(iterator(newnode), true);
}
template<class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::Lrotate(RBTreeNode<T>* cur)
{
Node* parent = cur->_parent;
Node* parpar = parent->_parent;
Node* subL = cur->_left;
parent->_right = subL;
if (subL)
{
subL->_parent = parent;
}
cur->_parent = parpar;
if (parpar)
{
if (parpar->_left == parent)
{
parpar->_left = cur;
}
else
{
parpar->_right = cur;
}
}
else
{
_root = cur;
cur->_parent = nullptr;
}
cur->_left = parent;
parent->_parent = cur;
cur->_col = BLACK;
parent->_col = RED;
}
template<class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::Rrotate(RBTreeNode<T>* cur)
{
Node* parent = cur->_parent;
Node* parpar = parent->_parent;
Node* subR = cur->_right;
parent->_left = subR;
if (subR)
{
subR->_parent = parent;
}
cur->_parent = parpar;
if (parpar)
{
if (parpar->_left == parent)
{
parpar->_left = cur;
}
else
{
parpar->_right = cur;
}
}
else
{
_root = cur;
cur->_parent = nullptr;
}
cur->_right = parent;
parent->_parent = cur;
cur->_col = BLACK;
parent->_col = RED;
}
template<class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::LRrotate(RBTreeNode<T>* cur)
{
Lrotate(cur);
Rrotate(cur);
}
template<class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::RLrotate(RBTreeNode<T>* cur)
{
Rrotate(cur);
Lrotate(cur);
}
my_map.h
namespace clx
{
template<class K, class V>
class my_map
{
public:
struct MapKeyOfT{
const K& operator()(const pair<K, V>& kv) {
return kv.first;}
};
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
iterator begin() {
return _t.begin(); }
iterator end() {
return _t.end(); }
iterator find(const K& k) {
return _t.find(k);}
pair<iterator, bool> insert(const pair<K, V>& kv) {
return _t.insert(kv);};
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.insert(make_pair(key, V()));
return ret.first->second;
}
void swap(my_map& m) {
swap(_t, m._t);}
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t;
};
void my_map_test()
{
my_map<string, string> m;
m.insert(make_pair("left", "左边"));
m.insert(make_pair("right", "右边"));
m.insert(make_pair("map", "地图"));
m["map"] = "1";
my_map<string, string> mm;
mm.insert(make_pair("clx", "no1"));
swap(m, mm);
my_map<string, string>::iterator it = m.begin();
while (it != m.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
my_map<string, string> copy2;
my_map<string, string> copy1;
copy1 = copy2= m;
for (auto e : copy2)
{
cout << e.first << ":" << e.second << endl;
}
for (auto e : copy1)
{
cout << e.first << ":" << e.second << endl;
}
//cout << endl;
//auto ret = m.find("left");
//cout << ret->first << (*ret).second << endl;
}
}
my_set.h
namespace clx
{
template<class K>
template<class K>
class my_set
{
public:
//仿函数
struct SetKeyOfT{
const K& operator()(const K& key) {
return key;}
};
typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
//迭代器相关接口
iterator begin() {
return _t.begin(); }
iterator end() {
return _t.end(); }
//查找
iterator find(const K& k) {
return _t.find(k);}
//插入
pair<iterator, bool> insert(const K& key) {
return _t.insert(key);};
//交换函数
void swap(my_set& s) {
swap(_t, s._t);}
private:
RBTree<K, K, SetKeyOfT> _t; //成员变量时是一棵搜索树
};
test.cpp
#include "my_map.h"
int main()
{
clx::my_map_test();
return 0;
}