BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslalg_rbtreeanchor.h
Go to the documentation of this file.
1/// @file bslalg_rbtreeanchor.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslalg_rbtreeanchor.h -*-C++-*-
8#ifndef INCLUDED_BSLALG_RBTREEANCHOR
9#define INCLUDED_BSLALG_RBTREEANCHOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$ $CSID$")
13
14/// @defgroup bslalg_rbtreeanchor bslalg_rbtreeanchor
15/// @brief Encapsulate root, first, and last nodes of a tree with a count.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslalg
19/// @{
20/// @addtogroup bslalg_rbtreeanchor
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslalg_rbtreeanchor-purpose"> Purpose</a>
25/// * <a href="#bslalg_rbtreeanchor-classes"> Classes </a>
26/// * <a href="#bslalg_rbtreeanchor-description"> Description </a>
27/// * <a href="#bslalg_rbtreeanchor-sentinel-node"> Sentinel Node </a>
28/// * <a href="#bslalg_rbtreeanchor-usage"> Usage </a>
29/// * <a href="#bslalg_rbtreeanchor-example-1-creating-a-simple-tree"> Example 1: Creating a Simple Tree </a>
30/// * <a href="#bslalg_rbtreeanchor-example-2-creating-an-insert-function-for-a-binary-tree"> Example 2: Creating an Insert Function for a Binary Tree </a>
31///
32/// # Purpose {#bslalg_rbtreeanchor-purpose}
33/// Encapsulate root, first, and last nodes of a tree with a count.
34///
35/// # Classes {#bslalg_rbtreeanchor-classes}
36///
37/// - bslalg::RbTreeAnchor: (in-core) node-addresses and node count
38///
39/// @see bslalg_rbtreenode, bslalg_rbtreeutil
40///
41/// # Description {#bslalg_rbtreeanchor-description}
42/// This component defines a single class, `RbTreeAnchor`,
43/// providing access to the addresses of the root, first, and sentinel nodes of
44/// a tree, as well as the count of the number of nodes. A sentinel node is a
45/// value-less node, owned by the `RbTreeAnchor` for the tree, that is used as
46/// the end-point for iteration over the nodes in a tree. `RbTreeAnchor`
47/// provides modifiers for the `firstNode`, `rootNode`, and `numNodes`
48/// properties, however the sentinel node for a tree is located at a fixed
49/// address and cannot be modified. An `RbTreeAnchor` is similar to an in-core
50/// unconstrained attribute class, except that it does not supply
51/// equality-comparison, copy-construction, and copy-assignment operations.
52///
53/// ## Sentinel Node {#bslalg_rbtreeanchor-sentinel-node}
54///
55///
56/// The sentinel node is an `RbTreeNode` object that does not have a value, and
57/// provides a fixed end-point for navigation over the tree. However, a
58/// sentinel node's attributes have different interpretations than those of
59/// other `RbTreeNode` objects. Specifically, a sentinel node's `leftChild`
60/// refers to the root of the tree, and its `rightChild` refers to the first
61/// node of the tree. The following diagram shows the composition of a tree
62/// with `RbTreeAnchor` and `RbTreeNode`:
63/// @code
64/// .------------------------.
65/// .------| RbTreeAnchor |-------.
66/// | | | |
67/// firstNode | | .--------------. | | rootNode
68/// | | | RbTreeNode | | |
69/// | | | (sentinel) | | |
70/// | | `--------------' | |
71/// | | / ^ \ | |
72/// | `-----/-----|-------\----' |
73/// V / | \ V
74/// __________/ | \__________
75/// | | |
76/// | | |
77/// sentinel | root | | sentinel
78/// *right*-child | parentNode | | *left*-child
79/// | | |
80/// | .--------------. |
81/// | | RbTreeNode | <----------'
82/// | | (root) |
83/// | `--------------'
84/// | / \.
85/// | .------------. .------------.
86/// | | RbTreeNode | | RbTreeNode |
87/// | `------------' `------------'
88/// | / \.
89/// | .-----------------------------.
90/// | | |
91/// | | [Tree of RbTreeNodes] |
92/// | | |
93/// | |_____________________________|
94/// V / \.
95/// .------------. .------------.
96/// | RbTreeNode | | RbTreeNode |
97/// | (first) | | (last) |
98/// `------------' `------------'
99/// @endcode
100/// Notice that, counter-intuitively, the sentinel's right-child refers to the
101/// left-most (first) node of the tree. Also notice that `RbTreeAnchor`
102/// doesn't hold a direct reference to the last (i.e., the right-most) node of
103/// the tree.
104///
105/// ## Usage {#bslalg_rbtreeanchor-usage}
106///
107///
108/// This section illustrates intended usage of this component.
109///
110/// ### Example 1: Creating a Simple Tree {#bslalg_rbtreeanchor-example-1-creating-a-simple-tree}
111///
112///
113/// This example demonstrates creating a simple tree of integer values using
114/// `RbTreeAnchor`. Note that, in practice, clients should use associated
115/// utilities to manage such a tree (see @ref bslalg_rbtreeutil ).
116///
117/// First, we define a node-type, `IntTreeNode`, that inherits from
118/// `RbTreeNode`:
119/// @code
120/// struct IntTreeNode : public RbTreeNode {
121/// // A red-black tree node containing an integer data-value.
122///
123/// int d_value; // "payload" value represented by the node
124/// };
125/// @endcode
126/// Then, we define `main` for our example, and create three nodes that we'll
127/// use to construct a tree:
128/// @code
129/// int main(int argc, const char *argv[])
130/// {
131/// IntTreeNode A, B, C;
132/// @endcode
133/// Next, we create an `RbTreeAnchor`, `myTree`, which will hold the addresses
134/// of the root node and the first node of our tree along with a count of nodes,
135/// and then verify the attribute values of the default constructed object:
136/// @code
137/// RbTreeAnchor myTree;
138/// assert(0 == myTree.rootNode());
139/// assert(myTree.sentinel() == myTree.firstNode());
140/// assert(0 == myTree.numNodes());
141/// @endcode
142/// Then, we describe the structure of the tree we wish to construct.
143/// @code
144///
145/// A (value: 2, BLACK)
146/// / \.
147/// / \.
148/// B (value: 1, RED) C ( value: 5, RED )
149/// @endcode
150/// Next, we set the properties for the nodes `A`, `B`, and `C` to form a valid
151/// tree whose structure matches that description:
152/// @code
153/// A.d_value = 2;
154/// A.makeBlack();
155/// A.setParent(myTree.sentinel());
156/// A.setLeftChild(&B);
157/// A.setRightChild(&C);
158///
159/// B.d_value = 1;
160/// B.makeRed();
161/// B.setParent(&A);
162/// B.setLeftChild(0);
163/// B.setRightChild(0);
164///
165/// C.d_value = 3;
166/// C.makeRed();
167/// C.setParent(&A);
168/// C.setLeftChild(0);
169/// C.setRightChild(0);
170/// @endcode
171/// Now, we assign the address of `A` and `B` as the root node and the first
172/// node of `myTree` respectively and set the number of nodes to 3:
173/// @code
174/// myTree.reset(&A, &B, 3);
175/// @endcode
176/// Finally, we verify the attributes of `myTree`:
177/// @code
178/// assert(&A == myTree.rootNode());
179/// assert(&B == myTree.firstNode());
180/// assert(3 == myTree.numNodes());
181/// @endcode
182///
183/// ### Example 2: Creating an Insert Function for a Binary Tree {#bslalg_rbtreeanchor-example-2-creating-an-insert-function-for-a-binary-tree}
184///
185///
186/// This example demonstrates creating a function that inserts elements into a
187/// binary search tree. Note that, for simplicity, this function does *not*
188/// create a balanced red-black tree (see @ref bslalg_rbtreeutil ).
189///
190/// First, we define a comparison functor for `IntTreeNode` objects used by the
191/// insertion function:
192/// @code
193/// struct IntTreeNodeComparator {
194/// // This class defines a comparator providing a comparison operation
195/// // between two 'IntTreeNode' objects.
196///
197/// bool operator()(const RbTreeNode& lhs, const RbTreeNode& rhs) const
198/// {
199/// return static_cast<const IntTreeNode&>(lhs).d_value <
200/// static_cast<const IntTreeNode&>(rhs).d_value;
201/// }
202/// };
203/// @endcode
204/// Then, we declare the signature of a function `insertNode`, which takes
205/// three arguments: (1) the anchor of the tree in which to insert the node (2)
206/// the new node to insert into the tree, and (3) a comparator, which is used to
207/// compare the payload values of the tree nodes. Note that the parameterized
208/// comparator is needed because a node's value is not accessible through the
209/// supplied `RbTreeNode`.
210/// @code
211/// template <class NODE_COMPARATOR>
212/// void insertNode(RbTreeAnchor *searchTree,
213/// RbTreeNode *newNode,
214/// const NODE_COMPARATOR& comparator)
215/// // Insert into the specified 'searchTree', ordered according to the
216/// // specified 'comparator', the specified 'newNode'. If there are
217/// // multiple nodes having the same value as 'newNode', insert 'newNode'
218/// // in the last position according to an infix traversal of the tree.
219/// // The behavior is undefined unless the 'comparator' provides a
220/// // strict weak ordering on the nodes in the tree.
221/// {
222/// @endcode
223/// Next, we find the location where `newNode` can be inserted into `searchTree`
224/// without violating the ordering imposed by `comparator`, and then updates
225/// `searchTree` with a potentially updated root node and first node.
226/// @code
227/// RbTreeNode *parent = searchTree->sentinel();
228/// RbTreeNode *node = searchTree->rootNode();
229/// bool isLeftChild;
230///
231/// newNode->setLeftChild(0);
232/// newNode->setRightChild(0);
233///
234/// if (!node) {
235/// @endcode
236/// If the root node of `searchTree` is 0, we use the `reset` function set the
237/// root node and the first node of `searchTree` to `newNode` and set the number
238/// of nodes to 1:
239/// @code
240/// searchTree->reset(newNode, newNode, 1);
241/// newNode->setParent(parent);
242/// return; // RETURN
243/// }
244///
245/// // Find the leaf node that would be a valid parent of 'newNode'.
246///
247/// do {
248/// parent = node;
249/// isLeftChild = comparator(*newNode, *node);
250/// if (isLeftChild) {
251/// node = parent->leftChild();
252/// }
253/// else {
254/// node = parent->rightChild();
255/// }
256/// } while (node);
257///
258/// // Insert 'newNode' into 'searchTree' and the location that's been
259/// // found.
260/// @endcode
261/// Then, we insert `newNode` into the appropriate position by setting it as a
262/// child of `parent`:
263/// @code
264/// if (isLeftChild) {
265/// // If 'newNode' is a left-child, it may be the new first node, but
266/// // cannot be the new last node.
267///
268/// parent->setLeftChild(newNode);
269/// newNode->setParent(parent);
270/// if (parent == searchTree->firstNode()) {
271/// searchTree->setFirstNode(newNode);
272/// }
273/// }
274/// else {
275/// parent->setRightChild(newNode);
276/// newNode->setParent(parent);
277/// }
278/// @endcode
279/// Next, we complete the insert function by incrementing the number of nodes in
280/// the tree:
281/// @code
282/// searchTree->incrementNumNodes();
283/// }
284/// @endcode
285/// Now, we create 5 `IntTreeNode` objects and insert them into a tree using the
286/// `insertNode` function.
287/// @code
288/// IntTreeNode nodes[5];
289///
290/// nodes[0].d_value = 3;
291/// nodes[1].d_value = 1;
292/// nodes[2].d_value = 5;
293/// nodes[3].d_value = 2;
294/// nodes[4].d_value = 0;
295///
296/// IntTreeNodeComparator comparator;
297///
298/// RbTreeAnchor anchor;
299/// for (int i = 0; i < 5; ++i) {
300/// insertNode(&anchor, nodes + i, comparator);
301/// }
302/// @endcode
303/// Finally, we verify that the `RbTreeAnchor` refers to the correct `TreeNode`
304/// with its `firstNode` and `rootNode` attributes.
305/// @code
306/// assert(0 == static_cast<IntTreeNode *>(anchor.firstNode())->d_value);
307/// assert(3 == static_cast<IntTreeNode *>(anchor.rootNode())->d_value);
308/// @endcode
309/// @}
310/** @} */
311/** @} */
312
313/** @addtogroup bsl
314 * @{
315 */
316/** @addtogroup bslalg
317 * @{
318 */
319/** @addtogroup bslalg_rbtreeanchor
320 * @{
321 */
322
323#include <bslscm_version.h>
324
325#include <bslalg_rbtreenode.h>
326
327#include <bslmf_assert.h>
328
329#include <bsls_assert.h>
330
331
332namespace bslalg {
333
334 // ==================
335 // class RbTreeAnchor
336 // ==================
337
338/// An `RbTreeAnchor` provides the addresses of the first and root nodes of
339/// a binary search tree. An `RbTreeAnchor` is similar to an in-core
340/// simply constrained (value-semantic) attribute class, except that it
341/// does not supply equality-comparison, copy-construction, and copy-assignment operations.
342///
343/// \note Note that a node may not be copied because
344/// `sentinel` returns an address unique to each `RbTreeAnchor` object.
345///
346/// This class:
347/// * is *exception-neutral*
348/// * is *alias-safe*
349/// * is `const` *thread-safe*
350/// For terminology see @ref bsldoc_glossary .
351///
352/// See @ref bslalg_rbtreeanchor
354
355 // DATA
356 RbTreeNode d_sentinel; // sentinel for the tree, holding the root,
357 // first and last tree nodes
358
359 int d_numNodes; // number of nodes
360
361 private:
362 // NOT IMPLEMENTED
364 RbTreeAnchor& operator=(const RbTreeAnchor&);
365
366 public:
367 // CREATORS
368
369 /// Create a `RbTree` object having the (default) attribute values:
370 /// @code
371 /// rootNode() == 0
372 /// firstNode() == sentinel()
373 /// numNodes() == 0
374 /// @endcode
375 RbTreeAnchor();
376
377 /// Create a `RbTreeAnchor` object having the specified `rootNode`,
378 /// `firstNode`, and `numNodes` attribute values.
381 int numNodes);
382
383 /// Destroy this object.
385
386 // MANIPULATORS
387
388 /// Set the `rootNode`, `firstNode`, and `numNodes`
389 /// attributes to the specified `rootNodeValue`, `firstNodeValue`,
390 /// and `numNodes` respectively.
393 int numNodes);
394
395 /// Set the `firstNode` attribute of this object to the specified
396 /// `value`.
397 void setFirstNode(RbTreeNode *value);
398
399 /// Set the `rootNode` attribute of this object to the specified
400 /// `value`.
401 void setRootNode(RbTreeNode *value);
402
403 /// Set the `numNodes` attribute of this object to the specified `value`.
404 ///
405 /// \pre The behavior is undefined unless `0 <= value`.
406 void setNumNodes(int value);
407
408 /// Increment, by 1, the `numNodes` attribute of this object.
409 ///
410 /// \pre The behavior is undefined unless `numNodes <= INT_MAX - 1`.
411 void incrementNumNodes();
412
413 /// Decrement, by 1, the `numNodes` attribute of this object.
414 ///
415 /// \pre The behavior is undefined unless `1 <= numNodes`.
416 void decrementNumNodes();
417
418 /// Return the address of the (modifiable) node referred to by the
419 /// `rootNode` attribute of this object.
421
422 /// Return the address of the (modifiable) node referred to by the
423 /// `firstNode` attribute of this object.
425
426 /// Return the address of the (modifiable) node referred to by the
427 /// `sentinel` node for this tree.
429
430 // ACCESSORS
431
432 /// Return the address referred to by the `firstNode` attribute of this
433 /// object.
434 const RbTreeNode *firstNode() const;
435
436 /// Return the address referred to by the `rootNode` attribute of this
437 /// object.
438 const RbTreeNode *rootNode() const;
439
440 /// Return the address referred to by the `sentinel` node for this tree.
441 const RbTreeNode *sentinel() const;
442
443 /// Return the `numNodes` attribute of this object.
444 int numNodes() const;
445};
446
447// ============================================================================
448// INLINE FUNCTION DEFINITIONS
449// ============================================================================
450
451 // ------------------
452 // class RbTreeAnchor
453 // ------------------
454
455// CREATORS
456inline
458: d_numNodes(0)
459{
460 d_sentinel.setRightChild(&d_sentinel);
461 d_sentinel.setLeftChild(0);
462}
463
464inline
466 RbTreeNode *firstNode,
467 int numNodes)
468: d_numNodes(numNodes)
469{
470 d_sentinel.setRightChild(firstNode);
471 d_sentinel.setLeftChild(rootNode);
472}
473
474inline
476{
477 BSLS_ASSERT_SAFE(sentinel()->leftChild() == rootNode());
478 BSLS_ASSERT_SAFE(sentinel()->rightChild() == firstNode());
479}
480
481// MANIPULATORS
482inline
484 RbTreeNode *firstNode,
485 int numNodes)
486{
487 d_sentinel.setLeftChild(rootNode);
488 d_sentinel.setRightChild(firstNode);
489 d_numNodes = numNodes;
490}
491
492inline
494{
495 d_sentinel.setRightChild(value);
496}
497
498inline
500{
501 d_sentinel.setLeftChild(value);
502}
503
504inline
506{
507 BSLS_ASSERT_SAFE(0 <= value);
508
509 d_numNodes = value;
510}
511
512inline
514{
515 ++d_numNodes;
516}
517
518inline
520{
521 --d_numNodes;
522}
523
524inline
526{
527 return d_sentinel.rightChild();
528}
529
530inline
532{
533 return d_sentinel.leftChild();
534}
535
536inline
538{
539 return &d_sentinel;
540}
541
542// ACCESSORS
543inline
545{
546 return d_sentinel.rightChild();
547}
548
549inline
551{
552 return d_sentinel.leftChild();
553}
554
555inline
557{
558 return d_numNodes;
559}
560
561inline
563{
564 return &d_sentinel;
565}
566
567} // close package namespace
568
569
570#endif
571
572// ----------------------------------------------------------------------------
573// Copyright 2013 Bloomberg Finance L.P.
574//
575// Licensed under the Apache License, Version 2.0 (the "License");
576// you may not use this file except in compliance with the License.
577// You may obtain a copy of the License at
578//
579// http://www.apache.org/licenses/LICENSE-2.0
580//
581// Unless required by applicable law or agreed to in writing, software
582// distributed under the License is distributed on an "AS IS" BASIS,
583// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
584// See the License for the specific language governing permissions and
585// limitations under the License.
586// ----------------------------- END-OF-FILE ----------------------------------
587
588/** @} */
589/** @} */
590/** @} */
Definition bslalg_rbtreeanchor.h:353
~RbTreeAnchor()
Destroy this object.
Definition bslalg_rbtreeanchor.h:475
void decrementNumNodes()
Definition bslalg_rbtreeanchor.h:519
RbTreeNode * sentinel()
Definition bslalg_rbtreeanchor.h:537
RbTreeNode * firstNode()
Definition bslalg_rbtreeanchor.h:525
void setNumNodes(int value)
Definition bslalg_rbtreeanchor.h:505
void setFirstNode(RbTreeNode *value)
Definition bslalg_rbtreeanchor.h:493
void setRootNode(RbTreeNode *value)
Definition bslalg_rbtreeanchor.h:499
RbTreeAnchor()
Definition bslalg_rbtreeanchor.h:457
int numNodes() const
Return the numNodes attribute of this object.
Definition bslalg_rbtreeanchor.h:556
RbTreeNode * rootNode()
Definition bslalg_rbtreeanchor.h:531
void incrementNumNodes()
Definition bslalg_rbtreeanchor.h:513
void reset(RbTreeNode *rootNode, RbTreeNode *firstNode, int numNodes)
Definition bslalg_rbtreeanchor.h:483
Definition bslalg_rbtreenode.h:377
RbTreeNode * rightChild()
Definition bslalg_rbtreenode.h:603
RbTreeNode * leftChild()
Definition bslalg_rbtreenode.h:597
void setRightChild(RbTreeNode *address)
Definition bslalg_rbtreenode.h:557
void setLeftChild(RbTreeNode *address)
Definition bslalg_rbtreenode.h:551
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlc_flathashmap.h:2218