底层实现set和map
- 红黑树的实现blog链接link.
1. 改进红黑树
通过STL可以得到,对于set和map的实现底层所使用的的都是红黑树,所以这里比较难得是对模板的使用。
#pragma once
enum Color
{
RED,
BLACK
};
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _t;
enum Color _col;
RBTreeNode(const T& t)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _t(t)
, _col(RED)
{}
};
template<class T, class Ref, class Ptr>
struct RBTreeIterator
{
typedef RBTreeIterator<T, Ref, Ptr> Self;
typedef RBTreeNode<T> Node;
Node* _node;
RBTreeIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_t;
}
//对于set来说,*it可以直接的取到Key值
//但是对于map来说,it->first
Ptr operator->()
{
return &(_node->_t);//如果是map那么这里返回的是一个pair<const K,V>*
}
// ++it 前置
//对于这个迭代器的++来说,还是比较需要在重新好好的思考一下的
Self& operator++()
{
//简单点说,当开始访问我这个结点的时候,说明这个结点的左树已经访问完了,此时分情况就要看右树是不是空
// 找中序的下一个
if (_node->_right)
{
// 右树的最左节点
Node* cur = _node->_right;
while (cur->_left)
{
cur = cur->_left;
}
_node = cur;
}
else
{
// 右为空,_node所在的子树已经访问完了,
// 沿着路径往根走,找孩子不是父亲的右的那个祖先
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && parent->_right == cur)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this; //*this返回的是本身
}
//对于++来说,左子树 根 右子树
//对于--来说,右子树 根 左子树,和++的逻辑刚好相反
Self& operator--()
{
//也就是当走到那个结点的时候,右子树和根已经遍历完了,所以此时应该看左子树
if (_node->_left)
{
//应该找左子树中的最右结点,也就是最大的结点
Node* cur = _node->_left;
while (cur->_right)
{
cur = cur->_right;
}
_node = cur;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && parent->_left == cur)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
};
// set<K> -> RBTree<K, K>
// map<K, V> -> RBTree<K,pair<const K, V>>
template<class K, class T, class KeyOfT>
struct RBTree
{
public:
typedef RBTreeIterator<T, T&, T*> Iterator;
typedef RBTreeIterator<T, const T&, const T*> Const_Iterator;
typedef RBTreeNode<T> Node;
//对于红黑树的Begin()迭代器来说,应该从中序遍历的第一个开始
Iterator Begin()
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return Iterator(cur);
}
Iterator End()
{
return Iterator(nullptr);
}
//bool Find(const K& k);
pair<Iterator, bool> Insert(const T& t)
{
KeyOfT kot;
if (_root == nullptr)
{
_root = new Node(t);
_root->_col = BLACK;
return make_pair(Iterator(_root), true);
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (kot(cur->_t) < kot(t))
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_t) > kot(t))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(Iterator(cur), false);
}
}
cur = new Node(t); // RED
if (kot(parent->_t) < kot(t))
{
parent->_right = cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
Node* newnode = cur;
//
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 = uncle->_col = BLACK;
grandfather->_col = RED;
// 继续往上处理
cur = grandfather;
parent = cur->_parent;
}
else // 情况2+3:u不存在或存在且为黑
{
// g
// p
// c
//
if (cur == parent->_left)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// g
// p
// c
//
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else // grandfather->_right == parent
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else // 情况2+3:u不存在或存在且为黑
{
if (cur == parent->_right)
{
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
else
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return make_pair(Iterator(newnode), true);
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* parentParent = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (parent == _root)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (parentParent->_left == parent)
{
parentParent->_left = subL;
}
else
{
parentParent->_right = subL;
}
subL->_parent = parentParent;
};
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
subR->_left = parent;
Node* parentParent = parent->_parent;
parent->_parent = subR;
if (_root == parent)
{
_root = subR;
}
else
{
if (parentParent->_left == parent)
{
parentParent->_left = subR;
}
else
{
parentParent->_right = subR;
}
}
subR->_parent = parentParent;
}
private:
Node* _root = nullptr;
};
- 红黑树的结点内存的不再是具体的类型Key值或者pair<const K,V>,而是一种更高维度的泛型,通过这个模板参数实现对同一颗树的复用。
- 对于模板所传了一个KeyOfT的仿函数的作用就是取出T模型中的K值,如果你是set那么T就是K,但是如果你是map的话,T就是pair<const K,V>,那么这里并不能拿来直接的比较大小,所以还需要将里面具体的Key值取出来,在进行比较大小才可以。
- 还有一个就是对于迭代器中的operator++()和operator–()需要好好的理解。对于迭代器的++操作来说,应该走的是中序遍历的过程,比如此时走到了7这个结点,下一个怎么找到,就是问题。
2. 对于set模拟封装
对于set和map来说,自己本身是没有什么内容的,他们就都是基于红黑树的基础上所实现的,底层所使用的也都是红黑树的结构和接口。
#pragma once
#include "RBTree.h"
namespace wzy
{
template<class K>
class set
{
struct SetKOfT
{
const K& operator()(const K& k)
{
return k;
}
};
public:
//对于set的迭代器其实就是对红黑树的迭代器进行了封装
//这里typename还有一个作用:此时代码走到这里,模板还没有实例化,所以找不到
//相当于告诉编译器,别急着报错,先放下,等待实例化之后再来找,如果还找不到,在报错也不急
typedef typename RBTree<K, K, SetKOfT>::Iterator iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
//pair<RBTreeNode<K>*, bool> insert(const K& k)
pair<iterator, bool> insert(const K& k)
{
return _t.Insert(k);
}
private:
RBTree<K, K, SetKOfT> _t;
};
void test_set()
{
set<int> s;
s.insert(1);
s.insert(20);
s.insert(12);
s.insert(2);
s.insert(23);
s.insert(21);
s.insert(2);
s.insert(30);
set<int>::iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout<<endl;
}
}
3. 对于map模拟封装
#pragma once
#include "RBTree.h"
namespace wzy
{
template<class K, class V>
class map
{
struct MapKOfT
{
const K& operator()(const pair<const K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree<K, pair<const K, V>, MapKOfT>::Iterator iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
//pair<RBTreeNode<pair<const K,V>>*, bool> insert(const pair<const K, V>& kv)
pair<iterator, bool> insert(const pair<const K, V>& kv)
{
return _t.Insert(kv);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert(make_pair(key, V()));
//ret.first拿到迭代器,->拿到了pair,然后返回第二个参数
return ret.first->second;
}
private:
RBTree<K, pair<const K, V>, MapKOfT> _t;
};
void test_map()
{
//map<int, int> m;
//m.insert(make_pair(1, 1));
//m.insert(make_pair(2, 1));
//m.insert(make_pair(3, 1));
//
//map<int, int>::iterator it = m.begin();
//while (it != m.end())
//{
// cout << it->first << " ";
// ++it;
//}
//cout << endl;
map<string, string> dict;
dict["string"] = "字符串";
dict["sort"] = "排序";
map<string, string>::iterator it = dict.begin();
while (it != dict.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
支持迭代器就支持范围for
//for (const auto& e : dict)
//{
// cout << e.first << ":" << e.second << endl;
//}
}
}
- 对于map来说是重载了[]的,但是底层其实就是调用insert函数帮忙实现的,不管成功不成功,返回的都是Value的引用。