Outline
Purpose
Provide a POD-like tree node type holding a parameterized value.
Classes
- See also
- bslstl_treenodefactory, bslstl_set, bslstl_map
Description
This component provides a single POD-like class, TreeNode
, used to represent a node in a red-black binary search tree holding a value of a parameterized type. A TreeNode
inherits from bslalg::RbTreeNode
, so it may be used with bslalg::RbTreeUtil
functions, and adds an attribute value
of the parameterized VALUE
. The following inheritance hierarchy diagram shows the classes involved and their methods:
,----------------.
`----------------'
| value
V
,------------------.
( bslalg::RbTreeNode )
`------------------'
ctor
dtor
makeBlack
makeRed
setParent
setLeftChild
setRightChild
setColor
toggleColor
parent
leftChild
rightChild
isBlack
isRed
color
Definition bslstl_treenode.h:393
This class is "POD-like" to facilitate efficient allocation and use in the context of a container implementation. In order to meet the essential requirements of a POD type, both this class
and bslalg::RbTreeNode
do not define a constructor or destructor. The manipulator, value
, returns a modifiable reference to the object that may be constructed in-place by the appropriate bsl::allocator_traits
object.
Usage
In this section we show intended usage of this component.
Example 1: Allocating and Deallocating TreeNode Objects.
In the following example we define a factory class for allocating and destroying TreeNode
objects.
First, we define the interface for the class NodeFactory
:
template <class VALUE, class ALLOCATOR>
class NodeFactory {
The parameterized ALLOCATOR
is intended to allocate objects of the parameterized VALUE
, so to use it to allocate objects of TreeNode<VALUE>
we must rebind it to the tree node type. Note that in general, we use allocator_traits
to perform actions using an allocator (including the rebind below):
rebind_traits<TreeNode<VALUE> > AllocatorTraits;
typedef typename AllocatorTraits::allocator_type NodeAllocator;
NodeAllocator d_allocator;
NodeFactory(const NodeFactory&);
NodeFactory& operator=(const NodeFactory&);
public:
NodeFactory(const ALLOCATOR& allocator);
TreeNode<VALUE> *createNode(const VALUE& value);
};
Definition bslalg_rbtreenode.h:376
Definition bslma_allocatortraits.h:1061
Now, we implement the NodeFactory
type:
template <class VALUE, class ALLOCATOR>
inline
NodeFactory<VALUE, ALLOCATOR>::NodeFactory(const ALLOCATOR& allocator)
: d_allocator(allocator)
{
}
We implement the createNode
function by using the rebound allocator_traits
for our allocator to in-place copy-construct the supplied value
into the value
data member of our result
node object. Note that TreeNode
is a POD-like type, without a constructor, so we do not need to call its constructor here:
template <class VALUE, class ALLOCATOR>
inline
TreeNode<VALUE> *
NodeFactory<VALUE, ALLOCATOR>::createNode(const VALUE& value)
{
TreeNode<VALUE> *result = AllocatorTraits::allocate(d_allocator, 1);
AllocatorTraits::construct(d_allocator,
value);
return result;
}
static TYPE * addressOf(TYPE &obj)
Definition bsls_util.h:305
Finally, we implement the function deleteNode
. Again, we use the rebound allocator_traits
for our tree node type, this time to destroy the value
date member of node, and then to deallocate its footprint. Note that TreeNode
is a POD-like type, so we do not need to call its destructor here:
template <class VALUE, class ALLOCATOR>
inline
{
TreeNode<VALUE> *treeNode = static_cast<TreeNode<VALUE> *>(node);
AllocatorTraits::destroy(d_allocator,
AllocatorTraits::deallocate(d_allocator, treeNode, 1);
}
Example 2: Creating a Simple Tree of TreeNode Objects.
In the following example we create a container-type Set
for holding a set of values of a parameterized VALUE
.
First, we define a comparator for VALUE
of TreeNode<VALUE>
objects. This type is designed to be supplied to functions in bslalg::RbTreeUtil
. Note that, for simplicity, this type uses operator<
to compare values, rather than a client defined comparator type.
template <class VALUE>
class Comparator {
public:
Comparator() {}
bool operator()(const VALUE& lhs,
const VALUE& rhs) const;
};
Then, we implement the comparison methods of Comparator
. Note that the supplied RbTreeNode
objects must be static_cast to TreeNode<VALUE>
to access their value:
template <class VALUE>
inline
bool Comparator<VALUE>::operator()(const VALUE& lhs,
{
return lhs < static_cast<const TreeNode<VALUE>& >(rhs).value();
}
template <class VALUE>
inline
const VALUE& rhs) const
{
return static_cast<const TreeNode<VALUE>& >(lhs).value() < rhs;
}
Now, having defined the requisite helper types, we define the public interface for Set
. Note that for the purposes of illustrating the use of TreeNode
a number of simplifications have been made. For example, this implementation provides only insert
, remove
, isMember
, and numMembers
operations:
template <class VALUE,
class Set {
typedef Comparator<VALUE> ValueComparator;
typedef NodeFactory<VALUE, ALLOCATOR> Factory;
Factory d_factory;
Set(const Set&);
Set& operator=(const Set&);
public:
Set(const ALLOCATOR& allocator = ALLOCATOR());
~Set();
void insert(const VALUE& value);
bool remove(const VALUE& value);
bool isElement(const VALUE& value) const;
int numElements() const;
};
Definition bslma_bslallocator.h:580
Definition bslalg_rbtreeanchor.h:352
Now, we define the implementation of Set
:
template <class VALUE, class ALLOCATOR>
inline
Set<VALUE, ALLOCATOR>::Set(const ALLOCATOR& allocator)
: d_tree()
, d_factory(allocator)
{
}
template <class VALUE, class ALLOCATOR>
inline
Set<VALUE, ALLOCATOR>::~Set()
{
}
template <class VALUE, class ALLOCATOR>
void Set<VALUE, ALLOCATOR>::insert(const VALUE& value)
{
int comparisonResult;
ValueComparator comparator;
&d_tree,
comparator,
value);
if (0 != comparisonResult) {
parent,
comparisonResult < 0,
node);
}
}
template <class VALUE, class ALLOCATOR>
bool Set<VALUE, ALLOCATOR>::remove(const VALUE& value)
{
if (node) {
d_factory.deleteNode(node);
}
return node;
}
template <class VALUE, class ALLOCATOR>
inline
bool Set<VALUE, ALLOCATOR>::isElement(const VALUE& value) const
{
ValueComparator comparator;
}
template <class VALUE, class ALLOCATOR>
inline
int Set<VALUE, ALLOCATOR>::numElements() const
{
}
int numNodes() const
Return the numNodes attribute of this object.
Definition bslalg_rbtreeanchor.h:552
static void remove(RbTreeAnchor *tree, RbTreeNode *node)
static void deleteTree(RbTreeAnchor *tree, FACTORY *nodeFactory)
Definition bslalg_rbtreeutil.h:1560
static void insertAt(RbTreeAnchor *tree, RbTreeNode *parentNode, bool leftChildFlag, RbTreeNode *newNode)
static RbTreeNode * findUniqueInsertLocation(int *comparisonResult, RbTreeAnchor *tree, NODE_VALUE_COMPARATOR &comparator, const VALUE &value)
Definition bslalg_rbtreeutil.h:1671
static const RbTreeNode * find(const RbTreeAnchor &tree, NODE_VALUE_COMPARATOR &comparator, const VALUE &value)
Definition bslalg_rbtreeutil.h:1343
Notice that the definition and implementation of Set
never directly uses the TreeNode
type, but instead use it indirectly through Comparator
, and NodeFactory
, and uses it via its base-class bslalg::RbTreeNode
.
Finally, we test our Set
.
Set<int> set;
assert(0 == set.numElements());
set.insert(1);
assert(set.isElement(1));
assert(1 == set.numElements());
set.insert(1);
assert(set.isElement(1));
assert(1 == set.numElements());
set.insert(2);
assert(set.isElement(1));
assert(set.isElement(2));
assert(2 == set.numElements());