目录
概述
算法
源码
Iterator.h
RBTree.h
Map.h
Set.h
test.cpp
map和set都是STL中的关联式容器,而vector、list、deque是序列式容器。
map是映像,set是集合,map元素的数据类型是std::pair
map和set的实现是对红黑树的封装,map根据key值进行排序,map和set的key值都是不可修改的,但是map的value值可以修改。
map和set支持迭代器、反向迭代器、常量迭代器,并且通过精妙的泛型设计,大大简化了代码,但是完成两个STL容器的基本功能封装,依旧需要千行代码左右。
本文里面的红黑树模块相较于上一篇博客,做了部分修改,设计了红黑树的迭代器,并将迭代器单独作为一个模块,通过普通迭代器构造出反向迭代器,这里采用的设计思路与之前 list 容器的迭代器设计思路是相同的。
红黑树在普通迭代器类中,设计出通过普通迭代器拷贝出const迭代器,这样解决了set模块的insert函数的返回值由红黑树的iterator转换为const_iterator问题。
红黑树迭代器的自增、自减都有其独特的算法,但是本文中的红黑树结构,与stl标准库中的红黑树略有不同,本文的红黑树没有一个空的头结点,即:当迭代器迭代到end(),即迭代器指向nullptr。而在stl标准库中,迭代器走到end()时,迭代器指向空的头结点。
红黑树的构造可以通过元素插入构造或者拷贝构造,拷贝构造设计了迭代器构造,这也是拷贝构造的核心。map和set的迭代器构造、拷贝构造、赋值构造本质都是调用红黑树的迭代器构造。
红黑树的泛型设计十分精妙(红黑树自身并不知道自己是要构造出一个map还是set,但是他必须兼容这两种容器的所有特性),并通过仿函数KofT设计,实现了从传入的元素数据(key值或key/value键值对)之中提取到key值进行排序
set模块的迭代器设计十分精妙,因为set里面元素都是key值,而红黑树的key值是不允许修改的,所以无论是set的普通迭代器iterator还是const_iterator,其本质都是const_iterator,所以set在设计时用const_iterator来重命名iterator,在普通迭代器的构造函数时加上了const修饰,而省略了const_iterator的构造函数,使iterator的构造函数能够对const_iterator构成重载。
map的 "[ ]" 运算符有特殊功能,即可以通过 "[ ] " 来进行数据插入、查找、统计,原理是:若 "[ ]" 里面数据的key值已经存在的话,则插入失败,insert函数返回已有节点的迭代器和一个bool值false,然后 "[ ] " 运算符返回这个迭代器(pair
#pragma once
enum Colour
{
RED,
BLACK
};
template
struct RBTreeNode
{
T _data;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Colour _col;
RBTreeNode(const T data)
: _data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED)
{}
};
template
struct RBTreeIterator
{
typedef RBTreeNode Node;
typedef RBTreeIterator Self;
typedef RBTreeIterator iterator;
Node* _node;
RBTreeIterator(Node* node)
: _node(node)
{}
// 普通迭代器构造const迭代器
RBTreeIterator(const iterator& it)
{
_node = it._node;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()
{
if (_node->_right)
{
Node* min = _node->_right;
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self operator++(int)
{
Self tmp(*this);
++(*this);
return tmp;
}
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;
while (parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self operator--(int)
{
Self tmp(*this);
--(*this);
return tmp;
}
bool operator!=(const Self& s)const
{
return _node != s._node;
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
};
template
struct RBTreeReverseIterator
{
typedef RBTreeReverseIterator Self;
Iterator _it;
RBTreeReverseIterator(Iterator it)
: _it(it)
{}
Ref operator*()
{
Iterator tmp = _it;
return *tmp;
}
Ptr operator->()
{
return &(operator*());
}
Self& operator++()
{
--_it;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
--_it;
return tmp;
}
Self& operator--()
{
++_it;
return *this;
}
Self operator--(int)
{
Self tmp(*this);
++_it;
return tmp;
}
bool operator!=(const Self& s)const
{
return _it != s._it;
}
bool operator==(const Self& s)const
{
return _it == s._it;
}
};
#pragma once
#include "Iterator.h"
template
class RBTree
{
// 私有
typedef RBTreeNode Node;
public:
typedef RBTreeIterator iterator;
typedef RBTreeIterator const_iterator;
typedef RBTreeReverseIterator reverse_iterator;
typedef RBTreeReverseIterator const_reverse_iterator;
iterator begin()
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin()const
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return const_iterator(left);
}
const_iterator end()const
{
return const_iterator(nullptr);
}
reverse_iterator rbegin()
{
Node* right = _root;
while (right && right->_right)
{
right = right->_right;
}
return reverse_iterator(iterator(right));
}
reverse_iterator rend()
{
return reverse_iterator(iterator(nullptr));
}
const_reverse_iterator rbegin()const
{
Node* right = _root;
while (right && right->_right)
{
right = right->_right;
}
return const_reverse_iterator(const_iterator(right));
}
const_reverse_iterator rend()const
{
return const_reverse_iterator(const_iterator(nullptr));
}
// 迭代器构造
template
RBTree(Iterator first, Iterator last)
{
_root = nullptr;
while (first != last)
{
insert(*first);
++first;
}
}
RBTree()
: _root(nullptr)
{}
std::pair insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return std::make_pair(iterator(_root), true);
}
KofT 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 std::make_pair(iterator(cur), false);
}
}
cur = new Node(data);
Node* newNode = cur;
cur->_col = RED;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
// 变色、旋转
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED)
{
// 情况1:叔叔存在且为红
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
if (cur == parent->_left)
{
// 情况2: 右单旋
rotate_right(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// 情况3: 左右双旋
rotate_left(parent);
rotate_right(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_left;
if (uncle&& uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
if (cur == parent->_right)
{
// 情况2: 左单旋
rotate_left(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// 情况3: 右左双旋
rotate_right(parent);
rotate_left(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return std::make_pair(iterator(newNode), true);
}
void rotate_right(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
subL->_right = parent;
Node* ppNode = parent->_parent;
parent->_parent = subL;
if (ppNode == nullptr)
{
subL->_parent = nullptr;
_root = subL;
}
else
{
if (parent == ppNode->_left)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
void rotate_left(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
subR->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = subR;
if (ppNode == nullptr)
{
subR->_parent = nullptr;
_root = subR;
}
else
{
if (parent == ppNode->_left)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
}
void in_order()
{
_in_order(_root);
std::cout << std::endl;
}
bool is_balance()
{
if (_root == nullptr)
{
return true;
}
if (_root->_col != BLACK)
{
return false;
}
int ref = 0;
Node* left = _root;
while (left)
{
if (left->_col == BLACK)
{
++ref;
}
left = left->_left;
}
return _is_balance(_root, 0, ref);
}
private:
void _in_order(Node* root)
{
if (root == nullptr)
{
return;
}
_in_order(root->_left);
std::cout << root->_data << std::endl;
_in_order(root->_right);
}
// 检查是否有联系的红节点
bool _is_balance(Node* root, int blackNum, const int ref)
{
if (root == nullptr)
{
if (blackNum != ref)
{
std::cout << "路径黑色节点跟最左路径不相等" << std::endl;
return false;
}
return true;
}
if (root->_col == RED && root->_parent->_col == RED)
{
std::cout << "出现连续红节点: " << root->_data.first << ", " << root->_parent->_data.first << std::endl;
return false;
}
if (root->_col == BLACK)
{
++blackNum;
}
return _is_balance(root->_left, blackNum, ref)
&& _is_balance(root->_right, blackNum, ref);
}
private:
Node* _root = nullptr;
};
#pragma once
#include "RBTree.h"
template
class Map
{
struct MapKofT
{
const K& operator()(const std::pair& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree, MapKofT>::iterator iterator;
typedef typename RBTree, MapKofT>::const_iterator const_iterator;
typedef typename RBTree, MapKofT>::reverse_iterator reverse_iterator;
typedef typename RBTree, MapKofT>::const_reverse_iterator const_reverse_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();
}
reverse_iterator rbegin()
{
return _t.rbegin();
}
reverse_iterator rend()
{
return _t.rend();
}
const_reverse_iterator rbegin()const
{
return _t.rbegin();
}
const_reverse_iterator rend()const
{
return _t.rend();
}
template
Map(Iterator first, Iterator last)
{
_t = RBTree, MapKofT>(first, last);
}
void swap(Map& m)
{
std::swap(_t, m._t);
}
Map()
: _t(RBTree, MapKofT>())
{}
Map(const Map& m)
{
Map tmp(m._t.begin(), m._t.end());
swap(tmp);
}
Map& operator=(const Map m)
{
swap(m);
return *this;
}
std::pair insert(const std::pair& kv)
{
return _t.insert(kv);
}
V& operator[](const K& key)
{
std::pair ret = insert(std::make_pair(key, V()));
return ret.first->second;
}
private:
RBTree, MapKofT> _t;
};
#pragma once
#include "RBTree.h"
template
class Set
{
struct SetKofT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree::const_iterator iterator;
typedef typename RBTree::const_iterator const_iterator;
typedef typename RBTree::const_reverse_iterator reverse_iterator;
typedef typename RBTree::const_reverse_iterator const_reverse_iterator;
iterator begin()const
{
return _t.begin();
}
iterator end()const
{
return _t.end();
}
reverse_iterator rbegin()const
{
return _t.rbegin();
}
reverse_iterator rend()const
{
return _t.rend();
}
template
Set(Iterator first, Iterator last)
{
_t = RBTree(first, last);
}
void swap(Set& s)
{
std::swap(_t, s._t);
}
Set()
: _t(RBTree())
{}
Set(const Set& s)
{
Set tmp(s.begin(), s.end());
swap(tmp);
}
Set& operator=(const Set s)
{
swap(s);
return *this;
}
std::pair insert(const K& k)
{
std::pair::iterator, bool> ret = _t.insert(k);
return std::pair(ret.first, ret.second);
}
private:
RBTree _t;
};
#include
#include
#include
#include "Map.h"
#include "Set.h"
void test_map()
{
int a[] = { 8, 4, 12, 2, 6, 10, 30, 14, 32, 28 };
Map m;
for (auto e : a)
{
m.insert(std::make_pair(e, e));
}
Map::iterator it = m.begin();
while (it != m.end())
{
std::cout << (*it).first << ": " << (*it).second << std::endl;
//++it;
it++;
}
std::cout << std::endl;
for (auto e : m)
{
std::cout << e.first << ": " << e.second << std::endl;
}
std::cout << std::endl;
Map::reverse_iterator rit = m.rbegin();
while (rit != m.rend())
{
std::cout << rit->first << ": " << rit->second << std::endl;
rit++;
}
std::cout << std::endl;
const Map m1(m.begin(), m.end());
Map::const_iterator cit = m1.begin();
while (cit != m1.end())
{
std::cout << cit->first << ": " << cit->second << std::endl;
cit++;
}
std::cout << std::endl;
const Map m2(m1);
Map::const_reverse_iterator crit = m2.rbegin();
while (crit != m2.rend())
{
std::cout << crit->first << ": " << crit->second << std::endl;
++crit;
}
std::cout << std::endl;
Map m3 = m2;
for (auto& e : m3)
{
// map的key不可修改,value可改
//e.first += 1;
e.second /= 2;
std::cout << e.first << ": " << e.second << std::endl;
}
std::cout << std::endl;
std::vector food = {
"蛋糕", "西瓜", "啤酒", "苹果", "香蕉", "蛋糕", "牛肉",
"西瓜", "苹果", "啤酒", "西瓜", "牛肉", "蛋糕", "蛋糕",
"西瓜", "西瓜", "牛肉", "苹果", "香蕉", "蛋糕", "西瓜"
};
Map foodMap;
for (auto& e : food)
{
foodMap[e]++;
}
for (auto& e : foodMap)
{
std::cout << e.first << ": " << e.second << std::endl;
}
std::cout << std::endl;
}
void test_set()
{
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
Set s;
for (auto e: a)
{
s.insert(e);
}
Set::iterator it = s.begin();
while (it != s.end())
{
std::cout << *it << ' ';
++it;
}
std::cout << std::endl;
for (const auto& e : s)
{
std::cout << e << ' ';
}
std::cout << std::endl;
Set::reverse_iterator rit = s.rbegin();
while (rit != s.rend())
{
std::cout << *rit << ' ';
++rit;
}
std::cout << std::endl;
const Set s1(s.begin(), s.end());
Set::const_iterator cit = s1.begin();
while (cit != s1.end())
{
std::cout << *cit << ' ';
++cit;
}
std::cout << std::endl;
const Set s2(s1);
Set::const_reverse_iterator crit = s2.rbegin();
while (crit != s2.rend())
{
std::cout << *crit << ' ';
++crit;
}
std::cout << std::endl;
const Set s3 = s2;
for (auto& e : s3)
{
// set的值不可修改
// e++;
std::cout << e << ' ';
}
std::cout << std::endl;
}
int main()
{
test_map();
test_set();
return 0;
}