blob: 446e1ed8a6ed212aab665b460348cd4478d655a3 [file] [log] [blame]
/** @file
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
namespace ts
{
namespace detail
{
/** A node in a red/black tree.
This class provides only the basic tree operations. The client
must provide the search and decision logic. This enables this
class to be a base class for templated nodes with much less code
duplication.
*/
struct RBNode {
typedef RBNode self; ///< self reference type
/// Node colors
typedef enum {
RED,
BLACK,
} Color;
/// Directional constants
typedef enum {
NONE,
LEFT,
RIGHT,
} Direction;
/// Get a child by direction.
/// @return The child in the direction @a d if it exists,
/// @c NULL if not.
self *getChild(Direction d //!< The direction of the desired child
) const;
/** Determine which child a node is
@return @c LEFT if @a n is the left child,
@c RIGHT if @a n is the right child,
@c NONE if @a n is not a child
*/
Direction
getChildDirection(self *const &n //!< The presumed child node
) const
{
return (n == _left) ? LEFT : (n == _right) ? RIGHT : NONE;
}
/** Get the parent node.
@return A Node* to the parent node or a @c nil Node* if no parent.
*/
self *
getParent() const
{
return const_cast<self *>(_parent);
}
/// @return The color of the node.
Color
getColor() const
{
return _color;
}
self *
leftmostDescendant() const
{
const self *n = this;
while (n->_left)
n = n->_left;
return const_cast<self *>(n);
}
/** Reverse a direction
@return @c LEFT if @a d is @c RIGHT, @c RIGHT if @a d is @c LEFT,
@c NONE otherwise.
*/
Direction
flip(Direction d)
{
return LEFT == d ? RIGHT : RIGHT == d ? LEFT : NONE;
}
/** Perform internal validation checks.
@return 0 on failure, black height of the tree on success.
*/
int validate();
/// Default constructor.
RBNode() {}
/// Destructor (force virtual).
virtual ~RBNode() {}
/** Rotate the subtree rooted at this node.
The node is rotated in to the position of one of its children.
Which child is determined by the direction parameter @a d. The
child in the other direction becomes the new root of the subtree.
If the parent pointer is set, then the child pointer of the original
parent is updated so that the tree is left in a consistent state.
@note If there is no child in the other direction, the rotation
fails and the original node is returned. It is @b not required
that a child exist in the direction specified by @a d.
@return The new root node for the subtree.
*/
self *rotate(Direction d //!< The direction to rotate
);
/** Set the child node in direction @a d to @a n.
The @a d child is set to the node @a n. The pointers in this
node and @a n are set correctly. This can only be called if
there is no child node already present.
@return @a n.
*/
self *setChild(self *n, //!< The node to set as the child
Direction d //!< The direction of the child
);
/** Remove this node from the tree.
The tree is rebalanced after removal.
@return The new root node.
*/
self *remove();
void
clearChild(Direction dir)
{
if (LEFT == dir)
_left = nullptr;
else if (RIGHT == dir)
_right = nullptr;
}
/** @name Subclass hook methods */
//@{
/** Structural change notification.
This method is called if the structure of the subtree rooted at
this node was changed.
This is intended a hook. The base method is empty so that subclasses
are not required to override.
*/
virtual void
structureFixup()
{
}
/** Called from @c validate to perform any additional validation checks.
Clients should chain this if they wish to perform additional checks.
@return @c true if the validation is successful, @c false otherwise.
@note The base method simply returns @c true.
*/
virtual bool
structureValidate()
{
return true;
}
//@}
/** Replace this node with another node.
This is presumed to be non-order modifying so the next reference
is @b not updated.
*/
void replaceWith(self *n //!< Node to put in place of this node.
);
//! Rebalance the tree starting at this node
/** The tree is rebalanced so that all of the invariants are
true. The (potentially new) root of the tree is returned.
@return The root node of the tree after the rebalance.
*/
self *rebalanceAfterInsert();
/** Rebalance the tree after a deletion.
Called on the lowest modified node.
@return The new root of the tree.
*/
self *rebalanceAfterRemove(Color c, //!< The color of the removed node.
Direction d //!< Direction of removed node from parent
);
//! Invoke @c structure_fixup() on this node and all of its ancestors.
self *rippleStructureFixup();
Color _color = RED; ///< node color
self *_parent = nullptr; ///< parent node (needed for rotations)
self *_left = nullptr; ///< left child
self *_right = nullptr; ///< right child
self *_next = nullptr; ///< Next node.
self *_prev = nullptr; ///< Previous node.
};
} /* namespace detail */
} /* namespace ts */