|
|
// xtree internal header #pragma once #ifndef _XTREE_ #define _XTREE_ #include <functional> #include <memory> #include <stdexcept>
#pragma pack(push,8) #pragma warning(push,3)
#pragma warning(disable:4127) _STD_BEGIN
// TEMPLATE CLASS _Tree_nod template<class _Traits> class _Tree_nod : public _Traits // traits form ultimate base { // base class for _Tree_ptr to hold allocator _Alnod protected: typedef typename _Traits::allocator_type allocator_type; typedef typename _Traits::key_compare key_compare; typedef typename _Traits::value_type value_type;
struct _Node; friend struct _Node; typedef typename allocator_type::_TEMPLATE_MEMBER rebind<_Node>::other::pointer _Genptr; // generic node pointer
struct _Node { // tree node _Node(_Genptr _Larg, _Genptr _Parg, _Genptr _Rarg, const value_type& _Val, char _Carg) : _Left(_Larg), _Parent(_Parg), _Right(_Rarg), _Myval(_Val), _Color(_Carg), _Isnil(false) { // construct a node with value }
_Genptr _Left; // left subtree, or smallest element if head _Genptr _Parent; // parent, or root of tree if head _Genptr _Right; // right subtree, or largest element if head value_type _Myval; // the stored value, unused if head char _Color; // _Red or _Black, _Black if head char _Isnil; // true only if head (also nil) node };
_Tree_nod(const key_compare& _Parg, allocator_type _Al) : _Traits(_Parg), _Alnod(_Al) { // construct traits from _Parg and allocator from _Al }
typename allocator_type::_TEMPLATE_MEMBER rebind<_Node>::other _Alnod; // allocator object for nodes };
// TEMPLATE CLASS _Tree_ptr template<class _Traits> class _Tree_ptr : public _Tree_nod<_Traits> { // base class for _Tree_val to hold allocator _Alptr protected: typedef typename _Tree_nod<_Traits>::_Node _Node; typedef typename _Traits::allocator_type allocator_type; typedef typename _Traits::key_compare key_compare; typedef typename allocator_type::_TEMPLATE_MEMBER rebind<_Node>::other::pointer _Nodeptr;
_Tree_ptr(const key_compare& _Parg, allocator_type _Al) : _Tree_nod<_Traits>(_Parg, _Al), _Alptr(_Al) { // construct base, and allocator from _Al }
typename allocator_type::_TEMPLATE_MEMBER rebind<_Nodeptr>::other _Alptr; // allocator object for pointers to nodes };
// TEMPLATE CLASS _Tree_val template<class _Traits> class _Tree_val : public _Tree_ptr<_Traits> { // base class for _Tree to hold allocator _Alval protected: typedef typename _Traits::allocator_type allocator_type; typedef typename _Traits::key_compare key_compare;
_Tree_val(const key_compare& _Parg, allocator_type _Al) : _Tree_ptr<_Traits>(_Parg, _Al), _Alval(_Al) { // construct base, and allocator from _Al }
allocator_type _Alval; // allocator object for values stored in nodes };
// TEMPLATE CLASS _Tree template<class _Traits> class _Tree : public _Tree_val<_Traits> { // ordered red-black tree for [multi_]{map set} public: typedef _Tree<_Traits> _Myt; typedef _Tree_val<_Traits> _Mybase; typedef typename _Traits::key_type key_type; typedef typename _Traits::key_compare key_compare; typedef typename _Traits::value_compare value_compare; typedef typename _Traits::value_type value_type; typedef typename _Traits::allocator_type allocator_type; typedef typename _Traits::_ITptr _ITptr; typedef typename _Traits::_IReft _IReft;
protected: typedef typename _Tree_nod<_Traits>::_Genptr _Genptr; typedef typename _Tree_nod<_Traits>::_Node _Node;
enum _Redbl { // colors for link to parent _Red, _Black}; typedef _POINTER_X(_Node, allocator_type) _Nodeptr; typedef _REFERENCE_X(_Nodeptr, allocator_type) _Nodepref; typedef _CREFERENCE_X(key_type, allocator_type) _Keyref; typedef _REFERENCE_X(char, allocator_type) _Charref; typedef _REFERENCE_X(value_type, allocator_type) _Vref;
static _Charref _Color(_Nodeptr _Pnode) { // return reference to color in node return ((_Charref)(*_Pnode)._Color); }
static _Charref _Isnil(_Nodeptr _Pnode) { // return reference to nil flag in node return ((_Charref)(*_Pnode)._Isnil); }
static _Keyref _Key(_Nodeptr _Pnode) { // return reference to key in node return (_Mybase::_Kfn(_Myval(_Pnode))); }
static _Nodepref _Left(_Nodeptr _Pnode) { // return reference to left pointer in node return ((_Nodepref)(*_Pnode)._Left); }
static _Nodepref _Parent(_Nodeptr _Pnode) { // return reference to parent pointer in node return ((_Nodepref)(*_Pnode)._Parent); }
static _Nodepref _Right(_Nodeptr _Pnode) { // return reference to right pointer in node return ((_Nodepref)(*_Pnode)._Right); }
static _Vref _Myval(_Nodeptr _Pnode) { // return reference to value in node return ((_Vref)(*_Pnode)._Myval); }
public: typedef typename allocator_type::size_type size_type; typedef typename allocator_type::difference_type _Dift; typedef _Dift difference_type; typedef _POINTER_X(value_type, allocator_type) _Tptr; typedef _CPOINTER_X(value_type, allocator_type) _Ctptr; typedef _REFERENCE_X(value_type, allocator_type) _Reft; typedef _Tptr pointer; typedef _Ctptr const_pointer; typedef _Reft reference; typedef _CREFERENCE_X(value_type, allocator_type) const_reference;
// CLASS const_iterator class const_iterator; friend class const_iterator;
class const_iterator : public _Bidit<value_type, _Dift, _Ctptr, const_reference> { // iterator for nonmutable _Tree public: typedef bidirectional_iterator_tag iterator_category; typedef _Dift difference_type; typedef _Ctptr pointer; typedef const_reference reference;
const_iterator() : _Ptr(0) { // construct with null node pointer }
const_iterator(_Nodeptr _Pnode) : _Ptr(_Pnode) { // construct with node pointer _Pnode }
const_reference operator*() const { // return designated value return (_Myval(_Ptr)); }
_Ctptr operator->() const { // return pointer to class object return (&**this); }
const_iterator& operator++() { // preincrement _Inc(); return (*this); }
const_iterator operator++(int) { // postincrement const_iterator _Tmp = *this; ++*this; return (_Tmp); }
const_iterator& operator--() { // predecrement _Dec(); return (*this); }
const_iterator operator--(int) { // postdecrement const_iterator _Tmp = *this; --*this; return (_Tmp); }
bool operator==(const const_iterator& _Right) const { // test for iterator equality return (_Ptr == _Right._Ptr); }
bool operator!=(const const_iterator& _Right) const { // test for iterator inequality return (!(*this == _Right)); }
void _Dec() { // move to node with next smaller value if (_Isnil(_Ptr)) _Ptr = _Right(_Ptr); // end() ==> rightmost else if (!_Isnil(_Left(_Ptr))) _Ptr = _Max(_Left(_Ptr)); // ==> largest of left subtree else { // climb looking for left subtree _Nodeptr _Pnode; while (!_Isnil(_Pnode = _Parent(_Ptr)) && _Ptr == _Left(_Pnode)) _Ptr = _Pnode; // ==> parent while left subtree if (!_Isnil(_Pnode)) _Ptr = _Pnode; // ==> parent if not head } }
void _Inc() { // move to node with next larger value if (_Isnil(_Ptr)) ; // end() shouldn't be incremented, don't move else if (!_Isnil(_Right(_Ptr))) _Ptr = _Min(_Right(_Ptr)); // ==> smallest of right subtree else { // climb looking for right subtree _Nodeptr _Pnode; while (!_Isnil(_Pnode = _Parent(_Ptr)) && _Ptr == _Right(_Pnode)) _Ptr = _Pnode; // ==> parent while right subtree _Ptr = _Pnode; // ==> parent (head if end()) } }
_Nodeptr _Mynode() const { // return node pointer return (_Ptr); }
protected: _Nodeptr _Ptr; // pointer to node };
// CLASS iterator class iterator; friend class iterator;
class iterator : public const_iterator { // iterator for mutable _Tree public: typedef bidirectional_iterator_tag iterator_category; typedef _Dift difference_type; typedef _ITptr pointer; typedef _IReft reference;
iterator() : const_iterator(0) { // construct with null node pointer }
iterator(_Nodeptr _Pnode) : const_iterator(_Pnode) { // construct with node pointer _Pnode }
reference operator*() const { // return designated value return (_Myval(_Ptr)); }
pointer operator->() const { // return pointer to class object return (&**this); }
iterator& operator++() { // preincrement _Inc(); return (*this); }
iterator operator++(int) { // postincrement iterator _Tmp = *this; ++*this; return (_Tmp); }
iterator& operator--() { // predecrement _Dec(); return (*this); }
iterator operator--(int) { // postdecrement iterator _Tmp = *this; --*this; return (_Tmp); } };
typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef pair<iterator, bool> _Pairib; typedef pair<iterator, iterator> _Pairii; typedef pair<const_iterator, const_iterator> _Paircc;
explicit _Tree(const key_compare& _Parg, const allocator_type& _Al) : _Mybase(_Parg, _Al) { // construct empty tree _Init(); }
_Tree(const value_type *_First, const value_type *_Last, const key_compare& _Parg, const allocator_type& _Al) : _Mybase(_Parg, _Al) { // construct tree from [_First, _Last) array _Init(); _TRY_BEGIN insert(_First, _Last); _CATCH_ALL _Tidy(); _RERAISE; _CATCH_END }
_Tree(const _Myt& _Right) : _Mybase(_Right.key_comp(), _Right.get_allocator()) { // construct tree by copying _Right _Init(); _TRY_BEGIN _Copy(_Right); _CATCH_ALL _Tidy(); _RERAISE; _CATCH_END }
~_Tree() { // destroy tree _Tidy(); }
_Myt& operator=(const _Myt& _Right) { // replace contents from _Right if (this != &_Right) { // worth doing erase(begin(), end()); this->comp = _Right.comp; _Copy(_Right); } return (*this); }
iterator begin() { // return iterator for beginning of mutable sequence return (iterator(_Lmost())); }
const_iterator begin() const { // return iterator for beginning of nonmutable sequence return (const_iterator(_Lmost())); }
iterator end() { // return iterator for end of mutable sequence return (iterator(_Myhead)); }
const_iterator end() const { // return iterator for end of nonmutable sequence return (const_iterator(_Myhead)); }
reverse_iterator rbegin() { // return iterator for beginning of reversed mutable sequence return (reverse_iterator(end())); }
const_reverse_iterator rbegin() const { // return iterator for beginning of reversed nonmutable sequence return (const_reverse_iterator(end())); }
reverse_iterator rend() { // return iterator for end of reversed mutable sequence return (reverse_iterator(begin())); }
const_reverse_iterator rend() const { // return iterator for end of reversed nonmutable sequence return (const_reverse_iterator(begin())); }
size_type size() const { // return length of sequence return (_Mysize); }
size_type max_size() const { // return maximum possible length of sequence return (this->_Alval.max_size()); }
bool empty() const { // return true only if sequence is empty return (size() == 0); }
allocator_type get_allocator() const { // return allocator object for values return (this->_Alval); }
key_compare key_comp() const { // return object for comparing keys return (this->comp); }
value_compare value_comp() const { // return object for comparing values return (value_compare(key_comp())); }
_Pairib insert(const value_type& _Val) { // try to insert node with value _Val _Nodeptr _Trynode = _Root(); _Nodeptr _Wherenode = _Myhead; bool _Addleft = true; // add to left of head if tree empty while (!_Isnil(_Trynode)) { // look for leaf to insert before (_Addleft) or after _Wherenode = _Trynode; _Addleft = this->comp(this->_Kfn(_Val), _Key(_Trynode)); _Trynode = _Addleft ? _Left(_Trynode) : _Right(_Trynode); }
if (this->_Multi) return (_Pairib(_Insert(_Addleft, _Wherenode, _Val), true)); else { // insert only if unique iterator _Where = iterator(_Wherenode); if (!_Addleft) ; // need to test if insert after is okay else if (_Where == begin()) return (_Pairib(_Insert(true, _Wherenode, _Val), true)); else --_Where; // need to test if insert before is okay
if (this->comp(_Key(_Where._Mynode()), this->_Kfn(_Val))) return (_Pairib(_Insert(_Addleft, _Wherenode, _Val), true)); else return (_Pairib(_Where, false)); } }
iterator insert(iterator _Where, const value_type& _Val) { // try to insert node with value _Val using _Where as a hint iterator _Next;
if (size() == 0) return (_Insert(true, _Myhead, _Val)); // insert into empty tree else if (this->_Multi) { // insert even if duplicate if (_Where == begin()) { // insert at beginning if before first element if (!this->comp(_Key(_Where._Mynode()), this->_Kfn(_Val))) return (_Insert(true, _Where._Mynode(), _Val)); } else if (_Where == end()) { // insert at end if after last element if (!this->comp(this->_Kfn(_Val), _Key(_Rmost()))) return (_Insert(false, _Rmost(), _Val)); } else if (!this->comp(_Key(_Where._Mynode()), this->_Kfn(_Val)) && !this->comp(this->_Kfn(_Val), _Key((--(_Next = _Where))._Mynode()))) { // insert before _Where if (_Isnil(_Right(_Next._Mynode()))) return (_Insert(false, _Next._Mynode(), _Val)); else return (_Insert(true, _Where._Mynode(), _Val)); } else if (!this->comp(this->_Kfn(_Val), _Key(_Where._Mynode())) && (++(_Next = _Where) == end() || !this->comp(_Key(_Next._Mynode()), this->_Kfn(_Val)))) { // insert after _Where if (_Isnil(_Right(_Where._Mynode()))) return (_Insert(false, _Where._Mynode(), _Val)); else return (_Insert(true, _Next._Mynode(), _Val)); } } else { // insert only if unique if (_Where == begin()) { // insert at beginning if before first element if (this->comp(this->_Kfn(_Val), _Key(_Where._Mynode()))) return (_Insert(true, _Where._Mynode(), _Val)); } else if (_Where == end()) { // insert at end if after last element if (this->comp(_Key(_Rmost()), this->_Kfn(_Val))) return (_Insert(false, _Rmost(), _Val)); } else if (this->comp(this->_Kfn(_Val), _Key(_Where._Mynode())) && this->comp(_Key((--(_Next = _Where))._Mynode()), this->_Kfn(_Val))) { // insert before _Where if (_Isnil(_Right(_Next._Mynode()))) return (_Insert(false, _Next._Mynode(), _Val)); else return (_Insert(true, _Where._Mynode(), _Val)); } else if (this->comp(_Key(_Where._Mynode()), this->_Kfn(_Val)) && (++(_Next = _Where) == end() || this->comp(this->_Kfn(_Val), _Key(_Next._Mynode())))) { // insert after _Where if (_Isnil(_Right(_Where._Mynode()))) return (_Insert(false, _Where._Mynode(), _Val)); else return (_Insert(true, _Next._Mynode(), _Val)); } }
return (insert(_Val).first); // try usual insert if all else fails }
template<class _Iter> void insert(_Iter _First, _Iter _Last) { // insert [_First, _Last) one at a time for (; _First != _Last; ++_First) insert(*_First); }
iterator erase(iterator _Where) { // erase element at _Where if (_Isnil(_Where._Mynode())) _THROW(out_of_range, "invalid map/set<T> iterator"); _Nodeptr _Fixnode; // the node to recolor as needed _Nodeptr _Fixnodeparent; // parent of _Fixnode (which may be nil) _Nodeptr _Erasednode = _Where._Mynode(); // node to erase _Nodeptr _Pnode = _Erasednode; ++_Where; // save successor iterator for return
if (_Isnil(_Left(_Pnode))) _Fixnode = _Right(_Pnode); // must stitch up right subtree else if (_Isnil(_Right(_Pnode))) _Fixnode = _Left(_Pnode); // must stitch up left subtree else { // two subtrees, must lift successor node to replace erased _Pnode = _Where._Mynode(); // _Pnode is successor node _Fixnode = _Right(_Pnode); // _Fixnode is its only subtree }
if (_Pnode == _Erasednode) { // at most one subtree, relink it _Fixnodeparent = _Parent(_Erasednode); if (!_Isnil(_Fixnode)) _Parent(_Fixnode) = _Fixnodeparent; // link up
if (_Root() == _Erasednode) _Root() = _Fixnode; // link down from root else if (_Left(_Fixnodeparent) == _Erasednode) _Left(_Fixnodeparent) = _Fixnode; // link down to left else _Right(_Fixnodeparent) = _Fixnode; // link down to right
if (_Lmost() == _Erasednode) _Lmost() = _Isnil(_Fixnode) ? _Fixnodeparent // smallest is parent of erased node : _Min(_Fixnode); // smallest in relinked subtree
if (_Rmost() == _Erasednode) _Rmost() = _Isnil(_Fixnode) ? _Fixnodeparent // largest is parent of erased node : _Max(_Fixnode); // largest in relinked subtree } else { // erased has two subtrees, _Pnode is successor to erased _Parent(_Left(_Erasednode)) = _Pnode; // link left up _Left(_Pnode) = _Left(_Erasednode); // link successor down
if (_Pnode == _Right(_Erasednode)) _Fixnodeparent = _Pnode; // successor is next to erased else { // successor further down, link in place of erased _Fixnodeparent = _Parent(_Pnode); // parent is successor's if (!_Isnil(_Fixnode)) _Parent(_Fixnode) = _Fixnodeparent; // link fix up _Left(_Fixnodeparent) = _Fixnode; // link fix down _Right(_Pnode) = _Right(_Erasednode); // link successor down _Parent(_Right(_Erasednode)) = _Pnode; // link right up }
if (_Root() == _Erasednode) _Root() = _Pnode; // link down from root else if (_Left(_Parent(_Erasednode)) == _Erasednode) _Left(_Parent(_Erasednode)) = _Pnode; // link down to left else _Right(_Parent(_Erasednode)) = _Pnode; // link down to right
_Parent(_Pnode) = _Parent(_Erasednode); // link successor up std::swap(_Color(_Pnode), _Color(_Erasednode)); // recolor it }
if (_Color(_Erasednode) == _Black) { // erasing black link, must recolor/rebalance tree for (; _Fixnode != _Root() && _Color(_Fixnode) == _Black; _Fixnodeparent = _Parent(_Fixnode)) if (_Fixnode == _Left(_Fixnodeparent)) { // fixup left subtree _Pnode = _Right(_Fixnodeparent); if (_Color(_Pnode) == _Red) { // rotate red up from right subtree _Color(_Pnode) = _Black; _Color(_Fixnodeparent) = _Red; _Lrotate(_Fixnodeparent); _Pnode = _Right(_Fixnodeparent); }
if (_Isnil(_Pnode)) _Fixnode = _Fixnodeparent; // shouldn't happen else if (_Color(_Left(_Pnode)) == _Black && _Color(_Right(_Pnode)) == _Black) { // redden right subtree with black children _Color(_Pnode) = _Red; _Fixnode = _Fixnodeparent; } else { // must rearrange right subtree if (_Color(_Right(_Pnode)) == _Black) { // rotate red up from left sub-subtree _Color(_Left(_Pnode)) = _Black; _Color(_Pnode) = _Red; _Rrotate(_Pnode); _Pnode = _Right(_Fixnodeparent); }
_Color(_Pnode) = _Color(_Fixnodeparent); _Color(_Fixnodeparent) = _Black; _Color(_Right(_Pnode)) = _Black; _Lrotate(_Fixnodeparent); break; // tree now recolored/rebalanced } } else { // fixup right subtree _Pnode = _Left(_Fixnodeparent); if (_Color(_Pnode) == _Red) { // rotate red up from left subtree _Color(_Pnode) = _Black; _Color(_Fixnodeparent) = _Red; _Rrotate(_Fixnodeparent); _Pnode = _Left(_Fixnodeparent); } if (_Isnil(_Pnode)) _Fixnode = _Fixnodeparent; // shouldn't happen else if (_Color(_Right(_Pnode)) == _Black && _Color(_Left(_Pnode)) == _Black) { // redden left subtree with black children _Color(_Pnode) = _Red; _Fixnode = _Fixnodeparent; } else { // must rearrange left subtree if (_Color(_Left(_Pnode)) == _Black) { // rotate red up from right sub-subtree _Color(_Right(_Pnode)) = _Black; _Color(_Pnode) = _Red; _Lrotate(_Pnode); _Pnode = _Left(_Fixnodeparent); }
_Color(_Pnode) = _Color(_Fixnodeparent); _Color(_Fixnodeparent) = _Black; _Color(_Left(_Pnode)) = _Black; _Rrotate(_Fixnodeparent); break; // tree now recolored/rebalanced } }
_Color(_Fixnode) = _Black; // ensure stopping node is black }
this->_Alnod.destroy(_Erasednode); // destroy, free erased node this->_Alnod.deallocate(_Erasednode, 1);
if (0 < _Mysize) --_Mysize;
return (_Where); // return successor iterator }
iterator erase(iterator _First, iterator _Last) { // erase [_First, _Last) if (_First == begin() && _Last == end()) { // erase all clear(); return (begin()); } else { // partial erase, one at a time while (_First != _Last) erase(_First++); return (_First); } }
size_type erase(const key_type& _Keyval) { // erase and count all that match _Keyval _Pairii _Where = equal_range(_Keyval); size_type _Num = 0; _Distance(_Where.first, _Where.second, _Num); erase(_Where.first, _Where.second); return (_Num); }
void erase(const key_type *_First, const key_type *_Last) { // erase all that match array of keys [_First, _Last) while (_First != _Last) erase(*_First++); }
void clear() { // erase all _Erase(_Root()); _Root() = _Myhead, _Mysize = 0; _Lmost() = _Myhead, _Rmost() = _Myhead; }
iterator find(const key_type& _Keyval) { // find an element in mutable sequence that matches _Keyval iterator _Where = lower_bound(_Keyval); return (_Where == end() || this->comp(_Keyval, _Key(_Where._Mynode())) ? end() : _Where); }
const_iterator find(const key_type& _Keyval) const { // find an element in nonmutable sequence that matches _Keyval const_iterator _Where = lower_bound(_Keyval); return (_Where == end() || this->comp(_Keyval, _Key(_Where._Mynode())) ? end() : _Where); }
size_type count(const key_type& _Keyval) const { // count all elements that match _Keyval _Paircc _Ans = equal_range(_Keyval); size_type _Num = 0; _Distance(_Ans.first, _Ans.second, _Num); return (_Num); }
iterator lower_bound(const key_type& _Keyval) { // find leftmost node not less than _Keyval in mutable tree return (iterator(_Lbound(_Keyval))); }
const_iterator lower_bound(const key_type& _Keyval) const { // find leftmost node not less than _Keyval in nonmutable tree return (const_iterator(_Lbound(_Keyval))); }
iterator upper_bound(const key_type& _Keyval) { // find leftmost node greater than _Keyval in mutable tree return (iterator(_Ubound(_Keyval))); }
const_iterator upper_bound(const key_type& _Keyval) const { // find leftmost node greater than _Keyval in nonmutable tree return (const_iterator(_Ubound(_Keyval))); }
_Pairii equal_range(const key_type& _Keyval) { // find range equivalent to _Keyval in mutable tree return (_Pairii(lower_bound(_Keyval), upper_bound(_Keyval))); }
_Paircc equal_range(const key_type& _Keyval) const { // find range equivalent to _Keyval in nonmutable tree return (_Paircc(lower_bound(_Keyval), upper_bound(_Keyval))); }
void swap(_Myt& _Right) { // exchange contents with _Right if (get_allocator() == _Right.get_allocator()) { // same allocator, swap control information std::swap(this->comp, _Right.comp); std::swap(_Myhead, _Right._Myhead); std::swap(_Mysize, _Right._Mysize); } else { // different allocator, do multiple assigns _Myt _Tmp = *this; *this = _Right, _Right = _Tmp; } }
protected: void _Copy(const _Myt& _Right) { // copy entire tree from _Right _Root() = _Copy(_Right._Root(), _Myhead); _Mysize = _Right.size(); if (!_Isnil(_Root())) { // nonempty tree, look for new smallest and largest _Lmost() = _Min(_Root()); _Rmost() = _Max(_Root()); } else _Lmost() = _Myhead, _Rmost() = _Myhead; // empty tree }
_Nodeptr _Copy(_Nodeptr _Rootnode, _Nodeptr _Wherenode) { // copy entire subtree, recursively _Nodeptr _Newroot = _Myhead; // point at nil node
if (!_Isnil(_Rootnode)) { // copy a node, then any subtrees _Nodeptr _Pnode = _Buynode(_Myhead, _Wherenode, _Myhead, _Myval(_Rootnode), _Color(_Rootnode)); if (_Isnil(_Newroot)) _Newroot = _Pnode; // memorize new root
_TRY_BEGIN _Left(_Pnode) = _Copy(_Left(_Rootnode), _Pnode); _Right(_Pnode) = _Copy(_Right(_Rootnode), _Pnode); _CATCH_ALL _Erase(_Newroot); // subtree copy failed, bail out _RERAISE; _CATCH_END }
return (_Newroot); // return newly constructed tree }
void _Erase(_Nodeptr _Rootnode) { // free entire subtree, recursively for (_Nodeptr _Pnode = _Rootnode; !_Isnil(_Pnode); _Rootnode = _Pnode) { // free subtrees, then node _Erase(_Right(_Pnode)); _Pnode = _Left(_Pnode); this->_Alnod.destroy(_Rootnode); // destroy, free erased node this->_Alnod.deallocate(_Rootnode, 1); } }
void _Init() { // create head/nil node and make tree empty _Myhead = _Buynode(); _Isnil(_Myhead) = true; _Root() = _Myhead; _Lmost() = _Myhead, _Rmost() = _Myhead; _Mysize = 0; }
iterator _Insert(bool _Addleft, _Nodeptr _Wherenode, const value_type& _Val) { // add node with value next to _Wherenode, to left if _Addnode if (max_size() - 1 <= _Mysize) _THROW(length_error, "map/set<T> too long"); _Nodeptr _Newnode = _Buynode(_Myhead, _Wherenode, _Myhead, _Val, _Red);
++_Mysize; if (_Wherenode == _Myhead) { // first node in tree, just set head values _Root() = _Newnode; _Lmost() = _Newnode, _Rmost() = _Newnode; } else if (_Addleft) { // add to left of _Wherenode _Left(_Wherenode) = _Newnode; if (_Wherenode == _Lmost()) _Lmost() = _Newnode; } else { // add to right of _Wherenode _Right(_Wherenode) = _Newnode; if (_Wherenode == _Rmost()) _Rmost() = _Newnode; }
for (_Nodeptr _Pnode = _Newnode; _Color(_Parent(_Pnode)) == _Red; ) if (_Parent(_Pnode) == _Left(_Parent(_Parent(_Pnode)))) { // fixup red-red in left subtree _Wherenode = _Right(_Parent(_Parent(_Pnode))); if (_Color(_Wherenode) == _Red) { // parent has two red children, blacken both _Color(_Parent(_Pnode)) = _Black; _Color(_Wherenode) = _Black; _Color(_Parent(_Parent(_Pnode))) = _Red; _Pnode = _Parent(_Parent(_Pnode)); } else { // parent has red and black children if (_Pnode == _Right(_Parent(_Pnode))) { // rotate right child to left _Pnode = _Parent(_Pnode); _Lrotate(_Pnode); } _Color(_Parent(_Pnode)) = _Black; // propagate red up _Color(_Parent(_Parent(_Pnode))) = _Red; _Rrotate(_Parent(_Parent(_Pnode))); } } else { // fixup red-red in right subtree _Wherenode = _Left(_Parent(_Parent(_Pnode))); if (_Color(_Wherenode) == _Red) { // parent has two red children, blacken both _Color(_Parent(_Pnode)) = _Black; _Color(_Wherenode) = _Black; _Color(_Parent(_Parent(_Pnode))) = _Red; _Pnode = _Parent(_Parent(_Pnode)); } else { // parent has red and black children if (_Pnode == _Left(_Parent(_Pnode))) { // rotate left child to right _Pnode = _Parent(_Pnode); _Rrotate(_Pnode); } _Color(_Parent(_Pnode)) = _Black; // propagate red up _Color(_Parent(_Parent(_Pnode))) = _Red; _Lrotate(_Parent(_Parent(_Pnode))); } }
_Color(_Root()) = _Black; // root is always black return (iterator(_Newnode)); }
_Nodeptr _Lbound(const key_type& _Keyval) const { // find leftmost node not less than _Keyval _Nodeptr _Pnode = _Root(); _Nodeptr _Wherenode = _Myhead; // end() if search fails
while (!_Isnil(_Pnode)) if (this->comp(_Key(_Pnode), _Keyval)) _Pnode = _Right(_Pnode); // descend right subtree else { // _Pnode not less than _Keyval, remember it _Wherenode = _Pnode; _Pnode = _Left(_Pnode); // descend left subtree }
return (_Wherenode); // return best remembered candidate }
_Nodeptr& _Lmost() { // return leftmost node in mutable tree return (_Left(_Myhead)); }
_Nodeptr& _Lmost() const { // return leftmost node in nonmutable tree return (_Left(_Myhead)); }
void _Lrotate(_Nodeptr _Wherenode) { // promote right node to root of subtree _Nodeptr _Pnode = _Right(_Wherenode); _Right(_Wherenode) = _Left(_Pnode);
if (!_Isnil(_Left(_Pnode))) _Parent(_Left(_Pnode)) = _Wherenode; _Parent(_Pnode) = _Parent(_Wherenode);
if (_Wherenode == _Root()) _Root() = _Pnode; else if (_Wherenode == _Left(_Parent(_Wherenode))) _Left(_Parent(_Wherenode)) = _Pnode; else _Right(_Parent(_Wherenode)) = _Pnode;
_Left(_Pnode) = _Wherenode; _Parent(_Wherenode) = _Pnode; }
static _Nodeptr _Max(_Nodeptr _Pnode) { // return rightmost node in subtree at _Pnode while (!_Isnil(_Right(_Pnode))) _Pnode = _Right(_Pnode); return (_Pnode); }
static _Nodeptr _Min(_Nodeptr _Pnode) { // return leftmost node in subtree at _Pnode while (!_Isnil(_Left(_Pnode))) _Pnode = _Left(_Pnode); return (_Pnode); }
_Nodeptr& _Rmost() { // return rightmost node in mutable tree return (_Right(_Myhead)); }
_Nodeptr& _Rmost() const { // return rightmost node in nonmutable tree return (_Right(_Myhead)); }
_Nodeptr& _Root() { // return root of mutable tree return (_Parent(_Myhead)); }
_Nodeptr& _Root() const { // return root of nonmutable tree return (_Parent(_Myhead)); }
void _Rrotate(_Nodeptr _Wherenode) { // promote left node to root of subtree _Nodeptr _Pnode = _Left(_Wherenode); _Left(_Wherenode) = _Right(_Pnode);
if (!_Isnil(_Right(_Pnode))) _Parent(_Right(_Pnode)) = _Wherenode; _Parent(_Pnode) = _Parent(_Wherenode);
if (_Wherenode == _Root()) _Root() = _Pnode; else if (_Wherenode == _Right(_Parent(_Wherenode))) _Right(_Parent(_Wherenode)) = _Pnode; else _Left(_Parent(_Wherenode)) = _Pnode;
_Right(_Pnode) = _Wherenode; _Parent(_Wherenode) = _Pnode; }
_Nodeptr _Ubound(const key_type& _Keyval) const { // find leftmost node greater than _Keyval _Nodeptr _Pnode = _Root(); _Nodeptr _Wherenode = _Myhead; // end() if search fails
while (!_Isnil(_Pnode)) if (this->comp(_Keyval, _Key(_Pnode))) { // _Pnode greater than _Keyval, remember it _Wherenode = _Pnode; _Pnode = _Left(_Pnode); // descend left subtree } else _Pnode = _Right(_Pnode); // descend right subtree
return (_Wherenode); // return best remembered candidate }
_Nodeptr _Buynode() { // allocate a head/nil node _Nodeptr _Wherenode = this->_Alnod.allocate(1, (void *)0); int _Linkcnt = 0;
_TRY_BEGIN this->_Alptr.construct(&_Left(_Wherenode), 0); ++_Linkcnt; this->_Alptr.construct(&_Parent(_Wherenode), 0); ++_Linkcnt; this->_Alptr.construct(&_Right(_Wherenode), 0); _CATCH_ALL if (1 < _Linkcnt) this->_Alptr.destroy(&_Parent(_Wherenode)); if (0 < _Linkcnt) this->_Alptr.destroy(&_Left(_Wherenode)); this->_Alnod.deallocate(_Wherenode, 1); _RERAISE; _CATCH_END _Color(_Wherenode) = _Black; _Isnil(_Wherenode) = false; return (_Wherenode); }
_Nodeptr _Buynode(_Nodeptr _Larg, _Nodeptr _Parg, _Nodeptr _Rarg, const value_type& _Val, char _Carg) { // allocate a node with pointers, value, and color _Nodeptr _Wherenode = this->_Alnod.allocate(1, (void *)0); _TRY_BEGIN new ((void *)_Wherenode) _Node(_Larg, _Parg, _Rarg, _Val, _Carg); _CATCH_ALL this->_Alnod.deallocate(_Wherenode, 1); _RERAISE; _CATCH_END return (_Wherenode); }
void _Tidy() { // free all storage erase(begin(), end()); this->_Alptr.destroy(&_Left(_Myhead)); this->_Alptr.destroy(&_Parent(_Myhead)); this->_Alptr.destroy(&_Right(_Myhead)); this->_Alnod.deallocate(_Myhead, 1); _Myhead = 0, _Mysize = 0; }
_Nodeptr _Myhead; // pointer to head node size_type _Mysize; // number of elements };
// _Tree TEMPLATE FUNCTIONS template<class _Traits> inline bool operator==(const _Tree<_Traits>& _Left, const _Tree<_Traits>& _Right) { // test for _Tree equality return (_Left.size() == _Right.size() && equal(_Left.begin(), _Left.end(), _Right.begin())); }
template<class _Traits> inline bool operator!=(const _Tree<_Traits>& _Left, const _Tree<_Traits>& _Right) { // test for _Tree inequality return (!(_Left == _Right)); }
template<class _Traits> inline bool operator<(const _Tree<_Traits>& _Left, const _Tree<_Traits>& _Right) { // test if _Less < _Right for _Trees return (lexicographical_compare(_Left.begin(), _Left.end(), _Right.begin(), _Right.end())); }
template<class _Traits> inline bool operator>(const _Tree<_Traits>& _Left, const _Tree<_Traits>& _Right) { // test if _Less > _Right for _Trees return (_Right < _Left); }
template<class _Traits> inline bool operator<=(const _Tree<_Traits>& _Left, const _Tree<_Traits>& _Right) { // test if _Less <= _Right for _Trees return (!(_Right < _Left)); }
template<class _Traits> inline bool operator>=(const _Tree<_Traits>& _Left, const _Tree<_Traits>& _Right) { // test if _Less >= _Right for _Trees return (!(_Left < _Right)); }
template<class _Traits> inline void swap(_Tree<_Traits>& _Left, _Tree<_Traits>& _Right) { // swap _Left and _Right trees _Left.swap(_Right); } _STD_END
#pragma warning(default:4127) #pragma warning(pop) #pragma pack(pop)
#endif /* _XTREE_ */
/* * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED. * Consult your license regarding permissions and restrictions. */
/* * This file is derived from software bearing the following * restrictions: * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this * software and its documentation for any purpose is hereby * granted without fee, provided that the above copyright notice * appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation. * Hewlett-Packard Company makes no representations about the * suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. V3.10:0009 */
|