红黑树中,封装map还是set是根据第二个节点参数决定的。
也就是说:树第一个参数是key,而第二个参数如果是set 就是 key,如果是map,则是pair。
RBTree.h#pragma once#include <iostream>
using namespace std;
#include <vector>
#include <set>enum Colour
{RED,BLACK
};template<class T> // T有可能是set中的key,也有可能是map中的pair
struct RBTreeNode
{RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;T _data;Colour _col;RBTreeNode(const T& data):_left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _col(RED){}
};template <class T, class Ref, class Ptr>
struct __RBTreeIterator
{typedef RBTreeNode<T> Node;typedef __RBTreeIterator<T, Ref, Ptr> Self;Node* _node;__RBTreeIterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const Self& s){return _node != s._node;}Self& operator++(){//中序遍历的下一个,对于当前节点而言,右树就是他的下一个,因此右不为空进循环if (_node->_right) {//下一个节点是右树的最左节点Node* leftMin = _node->_right;while (leftMin->_left){leftMin = leftMin->_left;}_node = leftMin;}else //右树是空的,则向上找,找到一个节点是父亲的左节点停止{Node* cur = _node;Node* parent = cur->_parent;//向上找,如果父亲不为空且当前节点是父亲的右一直技能循环,直到找到一个节点是父亲的左节点停止while (parent&&cur == parent->_right){cur = parent;parent = cur->_parent;}_node = parent;}return *this;}
};template<class K, class T, class KeyOfT> // T有可能是set中的key,也有可能是map中的pair
class RBTree
{typedef RBTreeNode<T> Node;
public:RBTree() = default;RBTree(const RBTree<K, T, KeyOfT>& t){_root = Copy(t._root);}Node* Copy(Node* root){if (root == nullptr)return nullptr;Node* newnode = new Node(root->_data);newnode->_col = root->_col;newnode->_left = Copy(root->_left);if (newnode->_left)newnode->_left->_parent = newnode;newnode->_right = Copy(root->_right);if (newnode->_right)newnode->_right->_parent = newnode;return newnode;}RBTree<K, T, KeyOfT>& operator=(RBTree<K, T, KeyOfT> t){swap(_root, t._root);return *this;}~RBTree(){Destory(_root);}void Destory(Node* root){if (root == nullptr)return;Destory(root->_left);Destory(root->_right);delete root;root = nullptr;}public:typedef __RBTreeIterator<T, T&, T*> Iterator;typedef __RBTreeIterator<T, const T&, const T*> ConstIterator;Iterator Begin(){Node* leftMin = _root;while (leftMin && leftMin->_left){leftMin = leftMin->_left;}return Iterator(leftMin);}Iterator End() //迭代器是左闭右开的,因此End是最右节点的下一个 也就是NULL{return Iterator(nullptr);}ConstIterator Begin() const{Node* leftMin = _root;while (leftMin && leftMin->_left){leftMin = leftMin->_left;}return ConstIterator(leftMin);}ConstIterator End() const{return ConstIterator(nullptr);}Iterator Find(const K& key) //find需要第一个K的模板参数{Node* cur = _root;KeyOfT kot;while (cur){if (kot(cur->_data) < key){cur = cur->_left;}else if (kot(cur->_data) >key){cur = cur->_right;}else{return Iterator(cur);}}return End();}pair<Iterator, bool> Insert(const T& data){//插入节点if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return make_pair(Iterator(_root), true);}//因此设计一个仿函数KeyOfT,利用这个函数返回出key就行了KeyOfT kot;Node* parent = nullptr;Node* cur = _root;while (cur){//set data是key//map data是pair pair不支持所需要的比较,因为我只需要比较pair的第一个,而pair默认的可能会比较第二个值//kot对象 是用来取T类型的data中的keyif (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else{return make_pair(Iterator(cur),false); // 找到了相等的位置就返回这个位置并插入失败}}cur = new Node(data);//最后返回的是newnode的迭代器,因为如果发生了旋转,cur就不是插入的时候的cur了Node* newnode = cur;cur->_col = RED;if (kot(parent->_data) < kot(data)){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//红黑树,如果有parent并且parent的颜色是红色,就需要调整while (parent&&parent->_col == RED){// 无论怎样调整,都得看叔叔Node* grandfather = parent->_parent;if (parent == grandfather->_left) //情况1{Node* uncle = grandfather->_right;//叔叔存在且为红->变色if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//变色后向上调整cur = grandfather;parent = cur->_parent;}else//叔叔不存在或者存在颜色为黑 则不用给u染色{if (cur == parent->_left) //情况2 3{RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else //cur == parent->right 情况4{RotateL(parent);RotateR(grandfather);cur->_col = BLACK; //旋转之后cur就在parent位置了,转变为94行代码的情况。grandfather->_col = RED;}break;}}else //右边的情况。{Node* uncle = grandfather->_left;//叔叔存在且为红色if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;grandfather->_col = RED;//向上调整cur = grandfather;parent = cur->_parent;}else //叔叔不存在或者是黑色{if (cur == parent->_right){RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}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;subL->_right = parent;Node* ppnode = parent->_parent; //得先把ppnode存下来才能更改parent->_parentparent->_parent = subL;if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = subL;}else{ppnode->_right = subL;}subL->_parent = ppnode;}}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = subR;subR->_left = parent;Node* ppnode = parent->_parent;parent->_parent = subR;if (parent == _root){_root = subR;subR->_parent = nullptr;}else{if (ppnode->_right == parent){ppnode->_right = subR;}else{ppnode->_left = subR;}subR->_parent = ppnode;}}void InOrder(){_InOrder(_root);cout << endl;}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 _IsBalance(_root, 0, refNum);}private:bool _IsBalance(Node* root, int blackNum, const int refNum){if (root == nullptr){if (blackNum != refNum){cout << "存在个数不相同的黑色节点" << endl;return false;}return true;}if (root->_col == BLACK)blackNum++;if (root->_col == RED && root->_parent->_col == RED){cout << "存在连续的红色节点" << endl;return false;}return _IsBalance(root->_left, blackNum, refNum)&& _IsBalance(root->_right, blackNum, refNum);}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_InOrder(root->_right);}private:Node* _root = nullptr;
};
set.h#pragma once#include "RBTree.h"namespace ggg
{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; //const是为了不能修改Ktypedef 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();}iterator find(const K& key){return _t.Find(key);}pair<iterator, bool> insert(const K& key){return _t.Insert(key);}private:RBTree<K, const K, SetKeyOfT> _t;};void PrintSet(const set<int>& s){for (auto e : s){cout << e << endl;}}void test_set(){set<int> s;s.insert(1);s.insert(7);s.insert(4);s.insert(0);s.insert(9);PrintSet(s);set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << endl;++it;}set<int> copy = s;for (auto e : copy){cout << e << " ";}cout << endl;}
}
map.h#pragma once#include "RBTree.h"
#include <string>namespace ggg
{template<class K, class V>class map{struct MapKeyOfT //写一个仿函数{const K& operator()(const pair<K, V>& key){return key.first;}};public:typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::Iterator iterator; //const是为了传参让pair中的K不能修改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> ret = _t.Insert(make_pair(key, V()));return ret.first->second;}private:RBTree<K, pair<const K, V>, MapKeyOfT> _t;};void test_map(){map<int,int> m;m.insert({ 3, 3 });m.insert({ 7, 7 });m.insert({ 0, 0 });m.insert({ 6, 6 });for (auto& e : m){cout << e.first << ":" << e.second << endl;}}void test_map2(){string arr[] = { "ggg1", "ggg2", "ggg2", "ggg2", "ggg3" };map<string, int> countMap;for (auto& e : arr){countMap[e]++;}for (auto& kv : countMap){cout << kv.first << ":" << kv.second << endl;}cout << endl;}
}