map和set的底层是使用红黑树来实现的,接下来我利用红黑树来模拟实现一下map和set。
map详解博客链接:https://blog.youkuaiyun.com/smx_dd/article/details/86531881
set详解博客链接:https://blog.youkuaiyun.com/smx_dd/article/details/86555973
红黑树详解与实现博客链接:https://blog.youkuaiyun.com/smx_dd/article/details/86632066
首先因为关联式容器中存储的是键值对,我们需要对之前实现的红黑树进行改造。
修改模板参数:template<class K,class ValueType,class KeyOfValue>
1. K代表key的类型
2. ValueType如果是map则表示键值对pair<K,V>;如果是set则表示K。
3. KeyOfValue:是通过ValueType获取Key值的一个仿函数类,因为我们在进行插入操作需要比较大小时,操作的是键值对无法直接比较大小,需要通过仿函数来获取要比较大小的值(key)来比较大小,仿函数就是在类中重载operator()函数,这样我们可以通过:类名+(),即创建一个该类的临时对象,通过该临时对象去访问operator(),从而可以将类当做函数一样来使用。
改造后的红黑树代码:MyRBTree.h
#pragma once
#include<iostream>
#include<string>
using namespace std;
enum Color
{
RED,
BLACK,
};
template<class T>
struct RBNode
{
RBNode<T>* left;
RBNode<T>* right;
RBNode<T>* parent;
T val;
Color color;
RBNode(const T& value = T(), Color _color = RED)
:left(nullptr)
, right(nullptr)
, parent(nullptr)
, val(value)
, color(_color)
{}
};
template<class T>
class Iterator
{
typedef RBNode<T> Node;
public:
Iterator(Node* _node = nullptr)
:pNode(_node)
{}
Iterator(const Iterator& it)
:pNode(it.pNode)
{}
T& operator*()
{
return pNode->val;
}
T* operator->()
{
return &(operator*());
}
Iterator<T>& operator++()
{
increasement();
return *this;
}
Iterator<T>& operator++(int)
{
Iterator<T> temp(*this);
increasement();
return temp;
}
Iterator<T>& operator--()
{
decreasement();
return *this;
}
Iterator<T>& operator--(int)
{
Iterator<T> temp(*this);
decreasement();
return temp;
}
bool operator!=(const Iterator& it)
{
return pNode != it.pNode;
}
bool operator==(const Iterator& it)
{
return pNode == it.pNode;
}
private:
void increasement()
{
if (pNode->right)
{
pNode = pNode->right;
while (pNode->left)
{
pNode = pNode->left;
}
}
else
{
Node* pParent = pNode->parent;
while (pParent->right == pNode)
{
pNode = pParent;
pParent = pParent->parent;
}
if (pNode->right != pParent)
{
pNode = pParent;
}
}
}
void decreasement()
{
if (pNode->parent->parent == pNode&&pNode->color == RED)
{
pNode = pNode->right;
}
else if (pNode->right)
{
pNode = pNode->left;
while (pNode->right)
{
pNode = pNode->right;
}
}
else
{
Node* pParent = pNode->parent;
while (pParent->left == pNode)
{
pNode = pParent;
pParent = pParent->parent;
}
pNode = pParent;
}
}
Node* pNode;
};
template<class K, class T,class KeyOfVlaue>
class RBTree
{
public:
typedef RBNode<T> Node;
typedef Iterator<T> _iterator;
_iterator begin()
{
return _iterator(header->left);
}
_iterator end()
{
return _iterator(header);
}
RBTree()
{
header = new Node;
header->parent = nullptr;
header->left = header;
header->right = header;
}
pair<_iterator, bool> insert(const T& value)
{
if (header->parent == nullptr)
{
Node* root = new Node(value, BLACK);
root->parent = header;
header->left = root;
header->right = root;
header->parent = root;
return make_pair(_iterator(root), true);
}
KeyOfVlaue keyofvalue;
Node* parent = nullptr;
Node* root = header->parent;
Node* cur = root;
while (cur)
{
if (keyofvalue(cur->val) > keyofvalue(value))
{
parent = cur;
cur = cur->left;
}
else if (keyofvalue(cur->val) < keyofvalue(value))
{
parent = cur;
cur = cur->right;
}
else
{
return make_pair(_iterator(cur), false);
}
}
cur = new Node(value, RED);
Node* newNode = cur;
if (keyofvalue(parent->val) > keyofvalue(cur->val))
{
parent->left = cur;
cur->parent = parent;
}
else
{
parent->right = cur;
cur->parent = parent;
}
while (cur != root&&cur->parent->color == RED)
{
parent = cur->parent;
Node* grandpa = parent->parent;
if (grandpa->left == parent)
{
Node* uncle = grandpa->right;
if (uncle&&uncle->color == RED)
{
parent->color = BLACK;
uncle->color = BLACK;
grandpa->color = RED;
cur = grandpa;
}
else
{
if (cur == parent->right)
{
rotateL(parent);
swap(parent, cur);
}
rotateR(grandpa);
parent->color = BLACK;
grandpa->color = RED;
break;
}
}
else
{
Node* uncle = grandpa->left;
if (uncle&&uncle->color == RED)
{
parent->color = BLACK;
uncle->color = BLACK;
grandpa->color = RED;
cur = grandpa;
}
else
{
if (cur == parent->left)
{
rotateR(parent);
swap(parent, cur);
}
rotateL(grandpa);
parent->color = BLACK;
grandpa->color = RED;
break;
}
}
}
header->parent->color = BLACK;
header->left = LeftMost();
header->right = RightMost();
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;
}
subL->right = parent;
Node* grandpa = parent->parent;
parent->parent = subL;
if (header->parent == parent)
{
header->parent = subL;
subL->parent = header;
}
else
{
if (grandpa->left == parent)
{
grandpa->left = subL;
}
else
{
grandpa->right = subL;
}
subL->parent = grandpa;
}
}
void rotateL(Node* parent)
{
Node* subR = parent->right;
Node* subRL = subR->left;
parent->right = subRL;
if (subRL)
{
subRL->parent = parent;
}
subR->left = parent;
Node* grandpa = parent->parent;
parent->parent = subR;
if (header->parent == parent)
{
header->parent = subR;
subR->parent = header;
}
else
{
if (grandpa->left == parent)
{
grandpa->left = subR;
}
else
{
grandpa->right = subR;
}
subR->parent = grandpa;
}
}
Node* LeftMost()
{
Node* cur = header->parent;
if (nullptr == cur)
{
return header;
}
while (cur->left)
{
cur = cur->left;
}
return cur;
}
Node* RightMost()
{
Node* cur = header->parent;
if (nullptr == cur)
{
return header;
}
while (cur->right)
{
cur = cur->right;
}
return cur;
}
void inorder()
{
_inorder(header->parent);
cout << endl;
}
bool empty()
{
return header->parent == nullptr;
}
bool IsValidRBTree()
{
Node* root = header->parent;
if (root == nullptr)
{
return true;
}
if (BLACK != root->color)
{
cout << "不满足根结点为黑色!" << endl;
return false;
}
size_t blackcount = 0;
Node* cur = root;
while (cur)
{
if (cur->color == BLACK)
{
++blackcount;
}
cur = cur->left;
}
size_t k = 0;
_IsValidRBTree(root, k, blackcount);
}
private:
Node* header;
void _inorder(Node* root)
{
if (root == nullptr)
{
return;
}
_inorder(root->left);
cout << root->val << " ";
_inorder(root->right);
}
bool _IsValidRBTree(Node* root, size_t k, size_t blackcount)
{
if (nullptr == root)
{
return true;
}
if (BLACK == root->color)
{
++k;
}
Node* pParent = root->parent;
if (pParent&&pParent->color == RED&&root->color == RED)
{
cout << "不满足不存在两个连接的红色节点!" << endl;
return false;
}
if (nullptr == root->left&&nullptr == root->right)
{
if (k != blackcount)
{
cout << "不满足每条路径上黑色节点个数相同!" << endl;
return false;
}
}
return _IsValidRBTree(root->left, k, blackcount) && _IsValidRBTree(root->right, k, blackcount);
}
};
map模拟实现:mymap.h
#include"MyRBTree.h"
template<class K, class V>
class map
{
class KeyOfValue //该内部类的作用是获取键值对的key值(仿函数类)
{
public:
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree<K, pair<K, V>, KeyOfValue>::_iterator iterator;
iterator begin()
{
return tree.begin();
}
iterator end()
{
return tree.end();
}
bool empty() const
{
return tree.empty();
}
V& operator[](const K& key)
{
return (*(tree.insert(make_pair(key, V()))).first).second;
}
pair<iterator, bool> insert(const pair<K, V>& kv)
{
return tree.insert(kv);
}
private:
RBTree<K, pair<K, V>, KeyOfValue> tree;
};
void testmap()
{
map<int, string> m;
m.insert(make_pair(3, "three"));
m.insert(make_pair(5, "five"));
m.insert(make_pair(4, "four"));
m.insert(make_pair(1, "one"));
m.insert(make_pair(2, "two"));
map<int, string>::iterator it = m.begin();
while (it != m.end())
{
cout << (*it).first << "-->" << (*it).second << " ";
cout << it->first << "-->" << it->second << endl;
it++;
}
m[6];
m[7] = "seven";
it = m.begin();
while (it != m.end())
{
cout << (*it).first << "-->" << (*it).second << " ";
cout << it->first << "-->" << it->second << endl;
it++;
}
cout << m[4] << endl;
}
map的一个特点就是重载了 operator[] 函数,而该函数的原理是,先插入,然后返回 value 值。
1. 我们先利用底层红黑树的插入,将键值对插入进去:tree.insert(make_pair(key,V()))
2. 红黑树的插入函数insert()返回的是pair<iterator,bool>键值对,该键值对的first值是一个迭代器,也就是键值对pair<key,value>的位置: (tree.insert(make_pair(key,V()))).first
3. 我们只要取出该键值对的second值,就是我们想要的value值: (*(tree.insert(make_pair(key,V()))).first).second
set的模拟实现:myset.h
set的模拟实现与map类似,只是没有重载 operator[] 函数,而且插入的只是一个key值
#include"MyRBTree.h"
template<class K>
class set
{
class KeyOfValue
{
public:
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K, K, KeyOfValue>::_iterator iterator;
iterator begin()
{
return tree.begin();
}
iterator end()
{
return tree.end();
}
bool empty() const
{
return tree.empty();
}
pair<iterator, bool> insert(const K& key)
{
return tree.insert(key);
}
private:
RBTree<K, K, KeyOfValue> tree;
};
void testset()
{
set<int> s;
s.insert(3);
s.insert(6);
s.insert(3);
s.insert(1);
s.insert(4);
s.insert(7);
s.insert(2);
set<int>::iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
it++;
}
cout << endl;
}