目錄
底層對比:
底層紅黑樹結構和set、map:?
底層模擬:
傳值調用:
迭代器:
operator ++()
?find函數
operator()?、仿函數?
set和map的仿函數 :
圖解:?
insert函數:
構造函數,析構函數:?
?析構函數:
拷貝構造函數:?
賦值函數:?
map的封裝:
set的封裝:?
紅黑樹的修改:?
底層對比:
上圖以kv模型為例?
通過底層可以看出:
- set和map的底層調用都是調用了紅黑樹 rb_tree
- set和map在底層最大的區別就是value的不同,set的value仍然是key類型的,但是map的value是pair<const key,T>類型的
- 也因為類型的不同,二者使用的template 類模板也相差了一個class T ,而這個class T表示的其實就是map的value中的second的數值類型
- 同時因為value的不同,所以導致了map和set在紅黑樹中存儲的數據也并不相同
底層紅黑樹結構和set、map:?
底層模擬:
傳值調用:
迭代器:
- 不論是set還是map 的迭代器,關鍵得是看紅黑樹的迭代器
- 樹的內部迭代器其實就是和鏈表相差不多,需要進行一個內部的重載調用
- 也就是說 operator-> operator * operator ++ operator --都是需要進行內部重載,然后進行封裝的!
RBTree.htemplate<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 = parent->_parent;}_node = parent;}return *this;}
};
operator ++()
是實現迭代器的難點之一,因為紅黑樹的本質其實是二叉搜索樹,所以遍歷是使用中序遍歷,所以++和--都是使用 中序遍歷的節點,如下圖所示,it所在位置的下一個節點是15?
?首先我們需要知道,中序遍歷的過程是 左子樹 根節點 右子樹 所以可以通過下圖右可以得出:
- 當前it所在的位置是它父親節點的左節點,那么下一個需要遍歷的節點就是it的父親節點
- 當前節點的右子樹是空的,那么表示這個節點的右子樹結束遍歷,下一個需要遍歷和++遞達的節點,應該往上進行查找祖先節點
- 如果當前節點的右子樹是空的,且當前節點是其父親節點的右節點,那么表示要去父親節點更往上的方向尋找下一個需要遍歷的節點
- 如果當前節點的右子樹是空的/遍歷完了,且當前節點是其父親節點的左節點,那么表示當前節點結束,返回父親節點且下一個訪問的節點就是父親節點,且同時訪問完后需要取父親節點的右子樹中進行遍歷和尋找下一個++位置的節點
- 最后一個單獨的處理,那就是走到最后一個節點的時候,走到最后一個節點的右子樹是空的,就一直返回到根節點,這時候就需要給迭代器置空了!
?
- ++的下一個節點是該節點右子樹中的最左節點!
- leftMin = node->right 表示進入右子樹中尋找最左節點,當然現在的條件是右子樹存在,如果右子樹存在就是上面,如果不存在就需要往上邊尋找,直到找到某個節點是它父親節點的左節點為止,或者說找到的某個節點,他沒有父親節點它是根節點為止!
- 要求當前的節點是他父親節點的右節點,如果一直是這樣就需要一直往上走,直到當前節點是它父親節點的左節點時,返回父親節點
- 且需要注意如果當前節點是根節點,那么它的父親就是空的,空的不能再繼續往上尋找了,所以直接跳出循環,最后返回父親節點!
RBTree.h
//紅黑樹中調動迭代器的函數方法
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(){return Iterator(nullptr);}ConstIterator End() const{return ConstIterator(nullptr);}ConstIterator Begin() const{Node* leftMin = _root;while (leftMin && leftMin->_left){leftMin = leftMin->_left;}return ConstIterator(leftMin);}
?find函數
RBTree.hIterator Find(const K& key){Node* cur = _root;while (cur){if (cur->_key < key){cur = cur->_right;}else if (cur->_key > key){cur = cur->_left;}else{return Iterator(cur);}}return End();}
operator()?、仿函數?
?使用仿函數的原因其實是在insert函數中需要使用operator()的原因,因為在insert函數中,需要使用比較大小之間的問題,而為了讓紅黑樹同時適應set和map(主要是針對map的pair內部問題),需要對取值之間進行正確取值的操作。
如上圖所示,在set中data可以直接對于set中的value,但是對于map來說,需要在pair中進行取值,所以map需要一個詳細的對應關系,這就造成了仿函數Key0fT的誕生
RBTree.h//樹的最終的基礎結構
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;
private:Node* _root = nullptr;
};
set和map的仿函數 :
//Myset.hstruct SetKeyOfT{const K& operator()(const K& key){return key;}};//Mymap.hstruct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};
圖解:?
insert函數:
pair<Iterator, bool> Insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return make_pair(Iterator(_root), true);}KeyOfT kot;//調用了仿函數,方便之后的比較Node* parent = nullptr;Node* cur = _root;while (cur){// K// pair<K, V>// 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);Node* newnode = cur;cur->_col = RED; // 新增節點給紅色if (kot(parent->_data) < kot(data)){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;// parent的顏色是黑色也結束while (parent && parent->_col == RED){// 關鍵看叔叔Node* grandfather = parent->_parent;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 // 叔叔不存在,或者存在且為黑{if (cur == parent->_left){// g // p u// c RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g // p u// c RotateL(parent);RotateR(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 // 叔叔不存在,或者存在且為黑{// 情況二:叔叔不存在或者存在且為黑// 旋轉+變色// g// u p// cif (cur == parent->_right){RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g// u p// cRotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}}_root->_col = BLACK;return make_pair(Iterator(newnode), true);}
構造函數,析構函數:?
?析構函數:
~RBTree(){Destroy(_root);_root = nullptr;}private:void Destroy(Node* root){if (root == nullptr)return;Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}
拷貝構造函數:?
?拷貝構造函數使用的是前序遍歷,且內部需要三條鏈接的拷貝和構造,也就是左子樹、右子樹、和父親節點,同時也需要進行節點顏色的拷貝操作,所以拷貝構造的內部其實是一個前序遍歷+顏色的拷貝+左右子樹的拷貝和鏈接+遞歸遍歷
RBTree(const RBTree<K, T, KeyOfT>& t){_root = Copy(t._root);}private:Node* Copy(Node* root){//因為要有父親節點的鏈接,所以需要一個反向鏈接//其次也需要進行顏色的拷貝!因為是紅黑樹!if (root == nullptr)return nullptr;Node* newroot = new Node(root->_data);newroot->_col = root->_col;newroot->_left = Copy(root->_left);if (newroot->_left)newroot->_left->_parent = newroot;newroot->_right = Copy(root->_right);if (newroot->_right)newroot->_right->_parent = newroot;return newroot;}
賦值函數:?
//RBTree.hRBTree<K, T, KeyOfT>& operator=(RBTree<K, T, KeyOfT> t){swap(_root, t._root);return *this;}
map的封裝:
namespace bit
{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, const K, MapKeyOfT>::ConstIterator const_iterator;const_iterator begin() const{return _t.Begin();}const_iterator end() const{return _t.End();}iterator begin() {return _t.Begin();}iterator end() {return _t.End();}iterator find(const K& key){return _t.Find(key);}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;};
set的封裝:?
namespace bit
{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;const_iterator begin() const{return _t.Begin();}const_iterator end() const{return _t.End();}iterator begin(){return _t.Begin();}iterator end(){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;}}
紅黑樹的修改:?
?
#pragma once
#include<vector>enum Colour
{RED,BLACK
};template<class T>
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 = parent->_parent;}_node = parent;}return *this;}
};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;RBTree() = default;RBTree(const RBTree<K, T, KeyOfT>& t){_root = Copy(t._root);}// t2 = t1RBTree<K, T, KeyOfT>& operator=(RBTree<K, T, KeyOfT> t){swap(_root, t._root);return *this;}~RBTree(){Destroy(_root);_root = nullptr;}Iterator Begin(){Node* leftMin = _root;while (leftMin && leftMin->_left){leftMin = leftMin->_left;}return Iterator(leftMin);}Iterator End(){return Iterator(nullptr);}ConstIterator End() const{return ConstIterator(nullptr);}ConstIterator Begin() const{Node* leftMin = _root;while (leftMin && leftMin->_left){leftMin = leftMin->_left;}return ConstIterator(leftMin);}Iterator Find(const K& key){Node* cur = _root;while (cur){if (cur->_key < key){cur = cur->_right;}else if (cur->_key > key){cur = cur->_left;}else{return Iterator(cur);}}return End();}// 20:10pair<Iterator, bool> Insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return make_pair(Iterator(_root), true);}KeyOfT kot;Node* parent = nullptr;Node* cur = _root;while (cur){// K// pair<K, V>// 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);Node* newnode = cur;cur->_col = RED; // 新增節點給紅色if (kot(parent->_data) < kot(data)){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;// parent的顏色是黑色也結束while (parent && parent->_col == RED){// 關鍵看叔叔Node* grandfather = parent->_parent;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 // 叔叔不存在,或者存在且為黑{if (cur == parent->_left){// g // p u// c RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g // p u// c RotateL(parent);RotateR(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 // 叔叔不存在,或者存在且為黑{// 情況二:叔叔不存在或者存在且為黑// 旋轉+變色// g// u p// cif (cur == parent->_right){RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g// u p// cRotateR(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;parent->_parent = subL;if (parent == _root){_root = subL;_root->_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 = parent;subR->_left = parent;Node* ppNode = parent->_parent;parent->_parent = subR;if (parent == _root){_root = subR;_root->_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->_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);}private:Node* Copy(Node* root){if (root == nullptr)return nullptr;Node* newroot = new Node(root->_data);newroot->_col = root->_col;newroot->_left = Copy(root->_left);if (newroot->_left)newroot->_left->_parent = newroot;newroot->_right = Copy(root->_right);if (newroot->_right)newroot->_right->_parent = newroot;return newroot;}void Destroy(Node* root){if (root == nullptr)return;Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}bool Check(Node* root, int blackNum, const int refNum){if (root == nullptr){//cout << blackNum << endl;if (refNum != blackNum){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);}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;//size_t _size = 0;
};
?