文章目錄 1. map和set的源碼及框架分析 2. 模擬實現map和set 2.1 實現可以復用紅黑樹的框架,支持insert操作 2.2 實現迭代器iterator 2.2.1 實現迭代器++ 2.2.2 實現迭代器 - - 2.2.3 解決key不能修改的問題 2.2.4 重載operator[ ] 3. 完整代碼 3.1 ==紅黑樹頭文件RBTree.h== 3.2 ==mymap頭文件== 3.3 ==myset頭文件== 3.4 ==測試文件test.cpp==
??學過紅黑樹后,現在我們來學習如何使用紅黑樹來封裝mymap和myset
1. map和set的源碼及框架分析
SGI-STL30版本源代碼,map和set的源代碼在map/set/stl_map.h/stl_set.h/stl_tree.h等幾個頭文件中
2. 模擬實現map和set
2.1 實現可以復用紅黑樹的框架,支持insert操作
當然,之前我們實現的紅黑樹是以map的key/value實現的,要實現泛型,就需要改變一些參數,例如節點數據應該給模版參數T,插入數據時應該是T& data
對比源碼調整一下,key參數就用K,value參數就用V,紅黑樹中的數據類型,我們使用T 其次因為RBTree實現了泛型不知道T參數到底是K,還是pair<K, V>,那么insert內部進行插入邏輯比較時,就沒辦法進行比較,因為pair的默認支持的是key和value一起參與比較,我們需要的是任何時候只比較key,所以我們在map和set層分別實現一個MapKeyOfT
和SetKeyOfT
的仿函數傳給RBTree的KeyOfT
,然后RBTree中通過KeyOfT
仿函數取出T類型對象中的key,再進行比較,具體細節參考如下代碼實現
2.2 實現迭代器iterator
迭代器實現時,其核心邏輯就是++/- -
時該如何實現 迭代器++的核心邏輯就是不看全局,只看局部,只考慮當前中序局部要訪問的下一個結點
實現迭代器的思路 1. 實現紅黑樹,封裝迭代器,使用紅黑樹封裝map和set 2. 實現迭代器++/- - 3. 搭建iterator和const_iterator框架 4. 解決key不支持修改的問題 5. 重載方括號operator[ ]
2.2.1 實現迭代器++
第一種情況:it所指向的節點,它的右子樹不為空,++it步驟
第2種情況: it所指向的節點,它的右子樹為空時,++it步驟
2.2.2 實現迭代器 - -
迭代器- -時思路和++時大同小異,這里直接上代碼講解
搭建iterator和const_iterator框架
2.2.3 解決key不能修改的問題
2.2.4 重載operator[ ]
3. 完整代碼
3.1 紅黑樹頭文件RBTree.h
# pragma once
# include <iostream>
using namespace std;
enum Colour
{ RED, BLACK
} ;
template < class T >
struct RBTreeNode
{ T _data; RBTreeNode< T> * _left; RBTreeNode< T> * _right; RBTreeNode< T> * _parent; Colour _col; RBTreeNode ( const T& data) : _data ( data) , _left ( nullptr ) , _right ( nullptr ) , _parent ( nullptr ) , _col ( RED) { }
} ;
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 = _node-> _right; while ( _node-> _left) { _node = _node-> _left; } } else { Node* cur = _node; Node* parent = cur-> _parent; while ( parent && cur == parent-> _right) { cur = parent; parent = parent-> _parent; } _node = parent; } return * this ; } Self& operator -- ( ) { 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-> _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* > Const_Iterator; RBTree ( ) = default ; Iterator begin ( ) { Node* MinLeft = _root; while ( MinLeft && MinLeft-> _left) { MinLeft = MinLeft-> _left; } return Iterator ( MinLeft, _root) ; } Iterator end ( ) { return Iterator ( nullptr , _root) ; } Const_Iterator begin ( ) const { Node* MinLeft = _root; while ( MinLeft && MinLeft-> _left) { MinLeft = MinLeft-> _left; } return Const_Iterator ( MinLeft, _root) ; } Const_Iterator end ( ) const { return Const_Iterator ( nullptr , _root) ; } pair< Iterator, bool > insert ( const T& data) { if ( _root == nullptr ) { _root = new Node ( data) ; _root-> _col = BLACK; return { Iterator{ _root, _root} , true } ; } KeyOfT kot; Node* parent = nullptr ; Node* cur = _root; while ( cur) { if ( kot ( data) > kot ( cur-> _data) ) { parent = cur; cur = cur-> _right; } else if ( kot ( data) < kot ( cur-> _data) ) { parent = cur; cur = cur-> _left; } else return { Iterator ( cur, _root) , false } ; } cur = new Node ( data) ; cur-> _col = RED; Node* newnode = cur; if ( kot ( data) > kot ( parent-> _data) ) parent-> _right = cur; else if ( kot ( data) < kot ( parent-> _data) ) 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) { uncle-> _col = parent-> _col = BLACK; grandfather-> _col = RED; cur = grandfather; parent = cur-> _parent; } else { if ( cur == parent-> _left) { RotateR ( grandfather) ; grandfather-> _col = RED; parent-> _col = BLACK; } else { RotateL ( parent) ; RotateR ( grandfather) ; grandfather-> _col = RED; cur-> _col = BLACK; } break ; } } else { Node* uncle = grandfather-> _left; if ( uncle && uncle-> _col == RED) { uncle-> _col = parent-> _col = BLACK; grandfather-> _col = RED; cur = grandfather; parent = cur-> _parent; } else { if ( cur == parent-> _right) { RotateL ( grandfather) ; grandfather-> _col = RED; parent-> _col = BLACK; } else { RotateR ( parent) ; RotateL ( grandfather) ; grandfather-> _col = RED; cur-> _col = BLACK; } break ; } } } _root-> _col = BLACK; return { Iterator{ newnode, _root} , true } ; } void RotateL ( Node* parent) { Node* subR = parent-> _right; Node* subRL = subR-> _left; parent-> _right = subRL; subR-> _left = parent; if ( subRL) subRL-> _parent = parent; Node* parent_Parent = parent-> _parent; parent-> _parent = subR; if ( parent_Parent == nullptr ) { _root = subR; subR-> _parent = nullptr ; } else { if ( parent_Parent-> _left == parent) parent_Parent-> _left = subR; else parent_Parent-> _right = subR; subR-> _parent = parent_Parent; } } void RotateR ( Node* parent) { Node* subL = parent-> _left; Node* subLR = subL-> _right; parent-> _left = subLR; subL-> _right = parent; if ( subLR) subLR-> _parent = parent; Node* parent_Parent = parent-> _parent; parent-> _parent = subL; if ( parent == _root) { _root = subL; subL-> _parent = nullptr ; } else { if ( parent_Parent-> _left == parent) parent_Parent-> _left = subL; else parent_Parent-> _right = subL; subL-> _parent = parent_Parent; } } void Inorder ( ) { _Inorder ( _root) ; cout << endl; } void _Inorder ( Node* root) { if ( root == nullptr ) return ; KeyOfT kot; _Inorder ( root-> _left) ; cout << kot ( root-> _data) << " " ; _Inorder ( root-> _right) ; } size_t Size ( ) { return _Size ( _root) ; } size_t _Size ( Node* root) { return root == nullptr ? 0 : _Size ( root-> _left) + _Size ( root-> _right) + 1 ; } Iterator Find ( const K& key) { Node* cur = _root; while ( cur) { if ( key > cur-> _kv. first) cur = cur-> _right; else if ( key < cur-> _kv. first) cur = cur-> _left; else return Iterator ( cur, _root) ; } return end ( ) ; } void Destroy ( Node* _root) { if ( _root == nullptr ) return ; Destroy ( _root-> _left) ; Destroy ( _root-> _right) ; delete _root; } ~ RBTree ( ) { Destroy ( _root) ; _root = nullptr ; } bool Check ( Node* root, int Count_BlackNode, int retNum) { if ( root == nullptr ) { if ( Count_BlackNode != retNum) { cout << "存在黑色節點數量不等的路徑" << endl; return false ; } return true ; } KeyOfT kot; if ( root-> _col == RED && root-> _parent-> _col == RED) { cout << kot ( root-> _data) << "存在連續的紅色節點" << endl; return false ; } if ( root-> _col == BLACK) { ++ Count_BlackNode; } return Check ( root-> _left, Count_BlackNode, retNum) && Check ( root-> _right, Count_BlackNode, retNum) ; } bool IsBalance ( ) { if ( _root == nullptr ) return true ; if ( _root-> _col == RED) { cout << "根節點為紅色!" << endl; return false ; } int retNum = 0 ; Node* cur = _root; while ( cur) { if ( cur-> _col == BLACK) { ++ retNum; } cur = cur-> _left; } return Check ( _root, 0 , retNum) ; } private : Node* _root = nullptr ;
} ;
3.2 mymap頭文件
# pragma once # include "RBTree_副本.h" namespace ZY
{ template < class K , class V > class mymap { 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> :: Const_Iterator const_iterator; pair< iterator, bool > insert ( const pair< K, V> & kv) { return _mymap. insert ( kv) ; } V& operator [ ] ( const K& key) { pair< iterator, bool > ret = _mymap. insert ( { key, V ( ) } ) ; return ret. first-> second; } bool IsBalance ( ) { return _mymap. IsBalance ( ) ; } size_t size ( ) { return _mymap. Size ( ) ; } void Inoreder ( ) { _mymap. Inorder ( ) ; } iterator begin ( ) { return _mymap. begin ( ) ; } iterator end ( ) { return _mymap. end ( ) ; } const_iterator begin ( ) const { return _mymap. begin ( ) ; } const_iterator end ( ) const { return _mymap. end ( ) ; } private : RBTree< K, pair< const K, V> , MapKeyOfT> _mymap; } ;
}
3.3 myset頭文件
# pragma once # include "RBTree_副本.h" namespace ZY
{ template < class K > class myset { 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> :: Const_Iterator const_iterator; pair< iterator, bool > insert ( const K& key) { return _myset. insert ( key) ; } bool IsBalance ( ) { return _myset. IsBalance ( ) ; } size_t size ( ) { return _myset. Size ( ) ; } void Inoreder ( ) { _myset. Inorder ( ) ; } iterator begin ( ) { return _myset. begin ( ) ; } iterator end ( ) { return _myset. end ( ) ; } const_iterator begin ( ) const { return _myset. begin ( ) ; } const_iterator end ( ) const { return _myset. end ( ) ; } private : RBTree< K, const K, SetKeyOfT> _myset; } ;
}
3.4 測試文件test.cpp
# include "mymap.h"
# include "myset.h"
# include <vector> void print_set ( const ZY:: myset< int > & s)
{ for ( auto e : s) { cout << e << " " ; } cout << endl;
} void print_map ( const ZY:: mymap< string, string> & mp)
{ for ( auto e : mp) { cout << e. first << " " << e. second << " " ; } cout << endl;
}
void myset_test1 ( )
{ ZY:: myset< int > st; int arr[ ] = { 4 , 2 , 6 , 1 , 3 , 5 , 15 , 7 , 16 , 14 } ; for ( auto & e : arr) { st. insert ( e) ; } if ( st. IsBalance ( ) ) cout << "該二叉樹是紅黑樹!" << endl; else cout << "該二叉樹不是紅黑樹!" << endl; cout << "節點個數:" << st. size ( ) << endl; ZY:: myset< int > :: iterator it = st. begin ( ) ; while ( it != st. end ( ) ) { cout << * it << " " ; ++ it; } cout << endl; print_set ( st) ;
} void mymap_test1 ( )
{ ZY:: mymap< string, string> mp; mp. insert ( { "left" , "左邊" } ) ; mp. insert ( { "right" , "右邊" } ) ; mp. insert ( { "sort" , "排序" } ) ; mp. insert ( { "string" , "字符串" } ) ; if ( mp. IsBalance ( ) ) cout << "該二叉樹是紅黑樹!" << endl; else cout << "該二叉樹不是紅黑樹!" << endl; cout << "節點個數:" << mp. size ( ) << endl; ZY:: mymap< string, string> :: iterator it = mp. begin ( ) ; while ( it != mp. end ( ) ) { cout << it-> first << ":" << it-> second << " " ; ++ it; } cout << endl; mp[ "哈哈哈" ] ; mp[ "left" ] = "耶耶耶" ; print_map ( mp) ;
} void test ( )
{ const int N = 1000000 ; vector< int > v; v. reserve ( N) ; srand ( time ( 0 ) ) ; for ( size_t i = 0 ; i < N; i++ ) { v. push_back ( i + rand ( ) ) ; } size_t begin2 = clock ( ) ; ZY:: myset< int > t; for ( size_t i = 0 ; i < v. size ( ) ; ++ i) { t. insert ( v[ i] ) ; } size_t end2 = clock ( ) ; cout << "Insert:" << end2 - begin2 << endl; cout << "Size:" << t. size ( ) << endl; if ( t. IsBalance ( ) ) cout << "該二叉樹是紅黑樹!" << endl; else cout << "該二叉樹不是紅黑樹!" << endl; } int main ( )
{ mymap_test1 ( ) ; return 0 ;
}