windows-nt/Source/XPSP1/NT/base/crts/libw32/include/xtree

1218 lines
34 KiB
Plaintext
Raw Normal View History

2020-09-26 03:20:57 -05:00
// 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;
}
}
friend void swap(_Myt& _Left, _Myt& _Right)
{ // swap _Left and _Right trees
_Left.swap(_Right);
}
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 OPERATORS
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));
}
_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 */