文章目录
前言
set,map底层使用红黑树这种平衡二叉搜索树来组织元素 ,这使得set, map能够提供对数时间复杂度的查找、插入和删除操作。
下面都是基于红黑树实现的set和map。
红黑树的改变
由于set和map是公用一棵树,set是K 、map是KV的结构,为了适应set与map的结构,红黑树要做出一定的改变.
- 仿函数是为了取到set内所存储的数据
- 在set的map中 set所存储的是key而map是pair
cpp
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
enum Color
{
RED,
BLACK
};
template<class T>
struct RBTreeNode
{
T _data;
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _col;
RBTreeNode(const T& data)
:_data(data),
_left(nullptr),
_right(nullptr),
_parent(nullptr)
{}
};
template<class T, class Ref, class Ptr>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, Ref, Ptr> Self;
Node* _node;
Node* _root;
RBTreeIterator(Node* node,Node* root)
:_node(node),
_root(root)
{}
//左 -> 根 -> 右
Self operator++()
{
//右不为空,右的最左(小)结点
if (_node->_right)
{
Node* min = _node->_right;
while (min && min->_left)
{
min = min->_left;
}
_node = min;
}
//右为空,找孩子是父亲左的结点
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && parent->_right == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
Self operator--()
{
// --end(),特殊处理,走到中序最后一个结点,整棵树的最右结点
if (_node == nullptr)
{
Node* rightMost = _root;
while (rightMost && rightMost->_right)
{
rightMost = rightMost->_right;
}
_node = rightMost;
}
// 左不为空,中序左的最右(大)结点
else if (_node->_left)
{
Node* rightMost = _node->_left;
while (rightMost && rightMost->_right)
{
rightMost = rightMost->_right;
}
_node = rightMost;
}
// 左为空,孩子是父亲右的那个祖先
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
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;
}
};
template<class K,class T,class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef RBTreeIterator<T, T&, T*> Iterator;
typedef RBTreeIterator<T, const T&, const T*> ConstIterator;
Iterator begin()
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return Iterator(cur, _root);
}
Iterator end()
{
return Iterator(nullptr, _root);
}
ConstIterator begin() const
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return Iterator(cur, _root);
}
ConstIterator end() const
{
return Iterator(nullptr, _root);
}
pair<Iterator,bool> Insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
//return pair<Iterator, bool>(Iterator(_root, _root), true);
return { Iterator(_root, _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 { Iterator(cur, _root), false };
}
}
cur = new Node(data);
Node* newnode = cur;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
cur->_col = RED;
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
// g
//p u
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
//存在为红,变色向上调整
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
//不存在或者为黑,旋转+变色
else
{
// g
// p
//c
if (cur == parent->_left)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
// g
// p
// c
else
{
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
// g
//u p
else
{
Node* uncle = grandfather->_left;
//存在为红,变色向上调整
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
//不存在或者为黑,旋转+变色
else
{
// g
// p
// c
if (cur == parent->_right)
{
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
// g
// p
// c
else
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return { Iterator(newnode, _root), true };
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* Pparent = parent->_parent;
if (subRL)
{
subRL->_parent = parent;
}
parent->_right = subRL;
parent->_parent = subR;
subR->_left = parent;
if (Pparent == nullptr)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (Pparent->_left == parent)
{
Pparent->_left = subR;
}
else
{
Pparent->_right = subR;
}
subR->_parent = Pparent;
}
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* Pparent = parent->_parent;
if (subLR)
{
subLR->_parent = parent;
}
parent->_left = subLR;
parent->_parent = subL;
subL->_right = parent;
if (Pparent == nullptr)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (Pparent->_left == parent)
{
Pparent->_left = subL;
}
else
{
Pparent->_right = subL;
}
subL->_parent = Pparent;
}
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
int Size()
{
return _Size(_root);
}
int Height()
{
return _Height(_root);
}
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < key)
{
cur = cur->_right;
}
else if(cur->_kv.first > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
bool IsBalance()
{
if (_root == nullptr)
{
return true;
}
if (_root->_col == RED)
{
return false;
}
int refNum = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
refNum++;
}
cur = cur->_left;
}
return Check(_root, 0, refNum);
}
~RBTree()
{
Destroy(_root);
_root = nullptr;
}
private:
void Destroy(Node* root)
{
if (root == nullptr)
{
return;
}
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << "->" << root->_col << endl;
_InOrder(root->_right);
}
int _Size(Node* root)
{
if (root == nullptr)
{
return 0;
}
return _Size(root->_left) + _Size(root->_right) + 1;
}
int _Height(Node* root)
{
if (root == nullptr)
{
return 0;
}
int leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
bool Check(Node* root, int blackNum, const int refNum)
{
if (root == nullptr)
{
//cout << blackNum << endl;
//说明一条路径已经走完了
if (blackNum != refNum)
{
cout << "存在黑色结点数量不相等的路径" << endl;
return false;
}
return true;
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << root->_kv.first << "出现连续的红色结点" << endl;
return false;
}
if (root->_col == BLACK)
{
blackNum++;
}
return Check(root->_left, blackNum, refNum) && Check(root->_right, blackNum, refNum);
}
private:
Node* _root = nullptr;
};
set的模拟实现
当前的红黑树需要这三个类型参数(键值、数据,通过数据求key的仿函数),这是为了map也能够复用,但是set只传入一个数据,所以采用这样的方式:<K, const K,SetKeyOfT< K >>,因为set中的数据是不能被修改的所以在第二个类型中加上const.
基本框架
cpp
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
private:
RBTree<K, const K,SetKeyOfT> _t;
};
迭代器
这里的迭代器直接复用红黑树的迭代器.
cpp
typedef typename RBTree<K,const K,SetKeyOfT>::Iterator iterator;
typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator 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();
}
插入
直接复用红黑树接口,其他的接口也是同样的道理
cpp
pair<iterator,bool> insert(const K& key)
{
return _t.Insert(key);
}
源码
cpp
#pragma once
namespace mihayou
{
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K,const K,SetKeyOfT>::Iterator iterator;
typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator 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();
}
pair<iterator,bool> insert(const K& key)
{
return _t.Insert(key);
}
~set()
{
}
private:
RBTree<K, const K,SetKeyOfT> _t;
};
}
map模拟实现
map给红黑树传的类型为:<K, pair<const K, V>, MapKeyOfT> ,K类型用于删除、查找等,pair<const K, V>作为数据插入,MapKeyOfT取pair<const K, V,>中的K类型,又因为键值不能修改所以pair<const K, V,>中的K加上const修饰.
基础框架
cpp
template<class K,class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
private:
RBTree<K, pair<const K,V>,MapKeyOfT> _t;
};
迭代器
cpp
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::Iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::ConstIterator 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();
}
插入
cpp
pair<iterator,bool> insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
赋值重载
在map里面,当key不存在时,重载[ ]就会用key进行插入操作并返回插入后key对应数据的引用(此时key对应数据是用其默认构造进行初始化的),当key存在时,返回key对应数据的引用。
cpp
V& operator[](const K& key)
{
pair<iterator, bool> it = insert({ key,V()});
return it.first->second;
}
源码
cpp
#pragma once
namespace mihayou
{
template<class K,class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::Iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::ConstIterator 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();
}
pair<iterator,bool> insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
V& operator[](const K& key)
{
pair<iterator, bool> it = insert({ key,V()});
return it.first->second;
}
~map()
{
}
private:
RBTree<K, pair<const K,V>,MapKeyOfT> _t;
};
}
测试代码
cpp
#include "RBTree.h"
#include "Myset.h"
#include "Mymap.h"
#include <string>
void Print(const mihayou::set<int>& s)
{
mihayou::set<int>::const_iterator it = s.end();
while (it != s.begin())
{
--it;
cout << *it << " ";
}
cout << endl;
}
void test01()
{
mihayou::set<int> s;
s.insert(1);
s.insert(5);
s.insert(3);
s.insert(7);
s.insert(6);
mihayou::set<int>::iterator itt = s.begin();
//*itt += 10;
while (itt != s.end())
{
cout << *itt << " ";
++itt;
}
cout << endl;
for (auto& e : s)
{
cout << e << " ";
}
cout << endl;
Print(s);
s.~set();
mihayou::map<string, string> dict;
dict.insert({ "sort", "排序" });
dict.insert({ "left", "左边" });
dict.insert({ "right", "右边" });
dict["left"] = "左边,剩余";
dict["insert"] = "插入";
dict["string"];
mihayou::map<string, string>::iterator it = dict.begin();
while (it != dict.end())
{
// 不能修改first,可以修改second
//it->first += 'x';
it->second += 'x';
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
for (auto& kv : dict)
{
cout << kv.first << ":" << kv.second << endl;
}
dict.~map();
}
int main()
{
test01();
return 0;
}