|
@@ -28,6 +28,7 @@
|
|
#include <dns/name.h>
|
|
#include <dns/name.h>
|
|
#include <boost/utility.hpp>
|
|
#include <boost/utility.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
+#include <boost/interprocess/offset_ptr.hpp>
|
|
#include <exceptions/exceptions.h>
|
|
#include <exceptions/exceptions.h>
|
|
#include <ostream>
|
|
#include <ostream>
|
|
#include <algorithm>
|
|
#include <algorithm>
|
|
@@ -89,6 +90,12 @@ private:
|
|
/// it.
|
|
/// it.
|
|
friend class RBTree<T>;
|
|
friend class RBTree<T>;
|
|
|
|
|
|
|
|
+ /// \brief Just a type alias
|
|
|
|
+ ///
|
|
|
|
+ /// We are going to use a lot of these offset pointers here and they
|
|
|
|
+ /// have a long name.
|
|
|
|
+ typedef boost::interprocess::offset_ptr<RBNode<T> > RBNodePtr;
|
|
|
|
+
|
|
/// \name Constructors
|
|
/// \name Constructors
|
|
///
|
|
///
|
|
/// \note The existence of a RBNode without a RBTree is meaningless.
|
|
/// \note The existence of a RBNode without a RBTree is meaningless.
|
|
@@ -323,14 +330,47 @@ private:
|
|
/// The overhead of the member pointers should be optimised out, as this
|
|
/// The overhead of the member pointers should be optimised out, as this
|
|
/// will probably get completely inlined into predecessor and successor
|
|
/// will probably get completely inlined into predecessor and successor
|
|
/// methods.
|
|
/// methods.
|
|
- const RBNode<T>* abstractSuccessor(RBNode<T>* RBNode<T>::*left,
|
|
|
|
- RBNode<T>* RBNode<T>::*right) const;
|
|
|
|
|
|
+ const RBNode<T>*
|
|
|
|
+ abstractSuccessor(typename RBNode<T>::RBNodePtr RBNode<T>::*left,
|
|
|
|
+ typename RBNode<T>::RBNodePtr RBNode<T>::*right)
|
|
|
|
+ const;
|
|
|
|
|
|
/// \name Data to maintain the rbtree structure.
|
|
/// \name Data to maintain the rbtree structure.
|
|
|
|
+ ///
|
|
|
|
+ /// We keep them as offset pointers. This is part of a future plan, when we
|
|
|
|
+ /// want to share the image of the tree between multiple processes.
|
|
|
|
+ /// However, whenever we have a chance, we switch to bare pointers during
|
|
|
|
+ /// the processing. The pointers on stack are never shared and the offset
|
|
|
|
+ /// pointers have non-trivial performance impact.
|
|
//@{
|
|
//@{
|
|
- RBNode<T>* parent_;
|
|
|
|
- RBNode<T>* left_;
|
|
|
|
- RBNode<T>* right_;
|
|
|
|
|
|
+ RBNodePtr parent_;
|
|
|
|
+ /// \brief Access the parent_ as bare pointer.
|
|
|
|
+ RBNode<T>* getParent() {
|
|
|
|
+ return (parent_.get());
|
|
|
|
+ }
|
|
|
|
+ /// \brief Access the parent_ as bare pointer, const.
|
|
|
|
+ const RBNode<T>* getParent() const {
|
|
|
|
+ return (parent_.get());
|
|
|
|
+ }
|
|
|
|
+ RBNodePtr left_;
|
|
|
|
+ /// \brief Access the left_ as bare pointer.
|
|
|
|
+ RBNode<T>* getLeft() {
|
|
|
|
+ return (left_.get());
|
|
|
|
+ }
|
|
|
|
+ /// \brief Access the left_ as bare pointer, const.
|
|
|
|
+ const RBNode<T>* getLeft() const {
|
|
|
|
+ return (left_.get());
|
|
|
|
+ }
|
|
|
|
+ RBNodePtr right_;
|
|
|
|
+ /// \brief Access the right_ as bare pointer.
|
|
|
|
+ RBNode<T>* getRight() {
|
|
|
|
+ return (right_.get());
|
|
|
|
+ }
|
|
|
|
+ /// \brief Access the right_ as bare pointer, const.
|
|
|
|
+ const RBNode<T>* getRight() const {
|
|
|
|
+ return (right_.get());
|
|
|
|
+ }
|
|
|
|
+ RBNodeColor color_;
|
|
//@}
|
|
//@}
|
|
|
|
|
|
/// \brief Relative name of the node.
|
|
/// \brief Relative name of the node.
|
|
@@ -347,7 +387,15 @@ private:
|
|
/// big flat tree into several hierarchy trees.
|
|
/// big flat tree into several hierarchy trees.
|
|
/// \li It saves memory usage as it allows storing only relative names,
|
|
/// \li It saves memory usage as it allows storing only relative names,
|
|
/// avoiding storage of the same domain labels multiple times.
|
|
/// avoiding storage of the same domain labels multiple times.
|
|
- RBNode<T>* down_;
|
|
|
|
|
|
+ RBNodePtr down_;
|
|
|
|
+ /// \brief Access the down_ as bare pointer.
|
|
|
|
+ RBNode<T>* getDown() {
|
|
|
|
+ return (down_.get());
|
|
|
|
+ }
|
|
|
|
+ /// \brief Access the down_ as bare pointer, const.
|
|
|
|
+ const RBNode<T>* getDown() const {
|
|
|
|
+ return (down_.get());
|
|
|
|
+ }
|
|
|
|
|
|
/// \brief If callback should be called when traversing this node in
|
|
/// \brief If callback should be called when traversing this node in
|
|
/// RBTree::find().
|
|
/// RBTree::find().
|
|
@@ -393,8 +441,9 @@ RBNode<T>::~RBNode() {
|
|
|
|
|
|
template <typename T>
|
|
template <typename T>
|
|
const RBNode<T>*
|
|
const RBNode<T>*
|
|
-RBNode<T>::abstractSuccessor(RBNode<T>* RBNode<T>::*left, RBNode<T>*
|
|
|
|
- RBNode<T>::*right) const
|
|
|
|
|
|
+RBNode<T>::abstractSuccessor(typename RBNode<T>::RBNodePtr RBNode<T>::*left,
|
|
|
|
+ typename RBNode<T>::RBNodePtr RBNode<T>::*right)
|
|
|
|
+ const
|
|
{
|
|
{
|
|
// This function is written as a successor. It becomes predecessor if
|
|
// This function is written as a successor. It becomes predecessor if
|
|
// the left and right pointers are swapped. So in case of predecessor,
|
|
// the left and right pointers are swapped. So in case of predecessor,
|
|
@@ -404,10 +453,11 @@ RBNode<T>::abstractSuccessor(RBNode<T>* RBNode<T>::*left, RBNode<T>*
|
|
const RBNode<T>* current = this;
|
|
const RBNode<T>* current = this;
|
|
// If it has right node, the successor is the left-most node of the right
|
|
// If it has right node, the successor is the left-most node of the right
|
|
// subtree.
|
|
// subtree.
|
|
- if (current->*right != RBNode<T>::NULL_NODE()) {
|
|
|
|
- current = current->*right;
|
|
|
|
- while (current->*left != RBNode<T>::NULL_NODE()) {
|
|
|
|
- current = current->*left;
|
|
|
|
|
|
+ if ((current->*right).get() != RBNode<T>::NULL_NODE()) {
|
|
|
|
+ current = (current->*right).get();
|
|
|
|
+ const RBNode<T>* left_n;
|
|
|
|
+ while ((left_n = (current->*left).get()) != RBNode<T>::NULL_NODE()) {
|
|
|
|
+ current = left_n;
|
|
}
|
|
}
|
|
return (current);
|
|
return (current);
|
|
}
|
|
}
|
|
@@ -415,10 +465,11 @@ RBNode<T>::abstractSuccessor(RBNode<T>* RBNode<T>::*left, RBNode<T>*
|
|
// Otherwise go up until we find the first left branch on our path to
|
|
// Otherwise go up until we find the first left branch on our path to
|
|
// root. If found, the parent of the branch is the successor.
|
|
// root. If found, the parent of the branch is the successor.
|
|
// Otherwise, we return the null node
|
|
// Otherwise, we return the null node
|
|
- const RBNode<T>* parent = current->parent_;
|
|
|
|
- while (parent != RBNode<T>::NULL_NODE() && current == parent->*right) {
|
|
|
|
|
|
+ const RBNode<T>* parent = current->getParent();
|
|
|
|
+ while (parent != RBNode<T>::NULL_NODE() &&
|
|
|
|
+ current == (parent->*right).get()) {
|
|
current = parent;
|
|
current = parent;
|
|
- parent = parent->parent_;
|
|
|
|
|
|
+ parent = parent->getParent();
|
|
}
|
|
}
|
|
return (parent);
|
|
return (parent);
|
|
}
|
|
}
|
|
@@ -1018,9 +1069,11 @@ public:
|
|
private:
|
|
private:
|
|
/// \name RBTree balance functions
|
|
/// \name RBTree balance functions
|
|
//@{
|
|
//@{
|
|
- void insertRebalance(RBNode<T>** root, RBNode<T>* node);
|
|
|
|
- RBNode<T>* rightRotate(RBNode<T>** root, RBNode<T>* node);
|
|
|
|
- RBNode<T>* leftRotate(RBNode<T>** root, RBNode<T>* node);
|
|
|
|
|
|
+ void insertRebalance(typename RBNode<T>::RBNodePtr* root, RBNode<T>* node);
|
|
|
|
+ RBNode<T>* rightRotate(typename RBNode<T>::RBNodePtr* root,
|
|
|
|
+ RBNode<T>* node);
|
|
|
|
+ RBNode<T>* leftRotate(typename RBNode<T>::RBNodePtr* root,
|
|
|
|
+ RBNode<T>* node);
|
|
//@}
|
|
//@}
|
|
|
|
|
|
/// \name Helper functions
|
|
/// \name Helper functions
|
|
@@ -1042,8 +1095,8 @@ private:
|
|
void nodeFission(RBNode<T>& node, const isc::dns::Name& sub_name);
|
|
void nodeFission(RBNode<T>& node, const isc::dns::Name& sub_name);
|
|
//@}
|
|
//@}
|
|
|
|
|
|
- RBNode<T>* NULLNODE;
|
|
|
|
- RBNode<T>* root_;
|
|
|
|
|
|
+ RBNode<T>* NULLNODE;
|
|
|
|
+ typename RBNode<T>::RBNodePtr root_;
|
|
/// the node count of current tree
|
|
/// the node count of current tree
|
|
unsigned int node_count_;
|
|
unsigned int node_count_;
|
|
/// search policy for rbtree
|
|
/// search policy for rbtree
|
|
@@ -1061,7 +1114,7 @@ RBTree<T>::RBTree(bool returnEmptyNode) :
|
|
|
|
|
|
template <typename T>
|
|
template <typename T>
|
|
RBTree<T>::~RBTree() {
|
|
RBTree<T>::~RBTree() {
|
|
- deleteHelper(root_);
|
|
|
|
|
|
+ deleteHelper(root_.get());
|
|
assert(node_count_ == 0);
|
|
assert(node_count_ == 0);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1073,25 +1126,28 @@ RBTree<T>::deleteHelper(RBNode<T>* root) {
|
|
}
|
|
}
|
|
|
|
|
|
RBNode<T>* node = root;
|
|
RBNode<T>* node = root;
|
|
- while (root->left_ != NULLNODE || root->right_ != NULLNODE) {
|
|
|
|
- while (node->left_ != NULLNODE || node->right_ != NULLNODE) {
|
|
|
|
- node = (node->left_ != NULLNODE) ? node->left_ : node->right_;
|
|
|
|
|
|
+ while (root->getLeft() != NULLNODE || root->getRight() != NULLNODE) {
|
|
|
|
+ RBNode<T>* left(NULLNODE);
|
|
|
|
+ RBNode<T>* right(NULLNODE);
|
|
|
|
+ while ((left = node->getLeft()) != NULLNODE ||
|
|
|
|
+ (right = node->getRight()) != NULLNODE) {
|
|
|
|
+ node = (left != NULLNODE) ? left : right;
|
|
}
|
|
}
|
|
|
|
|
|
- RBNode<T>* parent = node->parent_;
|
|
|
|
- if (parent->left_ == node) {
|
|
|
|
|
|
+ RBNode<T>* parent = node->getParent();
|
|
|
|
+ if (parent->getLeft() == node) {
|
|
parent->left_ = NULLNODE;
|
|
parent->left_ = NULLNODE;
|
|
} else {
|
|
} else {
|
|
parent->right_ = NULLNODE;
|
|
parent->right_ = NULLNODE;
|
|
}
|
|
}
|
|
|
|
|
|
- deleteHelper(node->down_);
|
|
|
|
|
|
+ deleteHelper(node->getDown());
|
|
delete node;
|
|
delete node;
|
|
--node_count_;
|
|
--node_count_;
|
|
node = parent;
|
|
node = parent;
|
|
}
|
|
}
|
|
|
|
|
|
- deleteHelper(root->down_);
|
|
|
|
|
|
+ deleteHelper(root->getDown());
|
|
delete root;
|
|
delete root;
|
|
--node_count_;
|
|
--node_count_;
|
|
}
|
|
}
|
|
@@ -1111,7 +1167,7 @@ RBTree<T>::find(const isc::dns::Name& target_name,
|
|
isc_throw(isc::BadValue, "RBTree::find is given a non empty chain");
|
|
isc_throw(isc::BadValue, "RBTree::find is given a non empty chain");
|
|
}
|
|
}
|
|
|
|
|
|
- RBNode<T>* node = root_;
|
|
|
|
|
|
+ RBNode<T>* node = root_.get();
|
|
Result ret = NOTFOUND;
|
|
Result ret = NOTFOUND;
|
|
isc::dns::Name name = target_name;
|
|
isc::dns::Name name = target_name;
|
|
|
|
|
|
@@ -1142,7 +1198,7 @@ RBTree<T>::find(const isc::dns::Name& target_name,
|
|
// but cheaper way).
|
|
// but cheaper way).
|
|
if (common_label_count == 1 && node->name_.getLength() != 1) {
|
|
if (common_label_count == 1 && node->name_.getLength() != 1) {
|
|
node = (node_path.last_comparison_.getOrder() < 0) ?
|
|
node = (node_path.last_comparison_.getOrder() < 0) ?
|
|
- node->left_ : node->right_;
|
|
|
|
|
|
+ node->getLeft() : node->getRight();
|
|
} else if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
|
|
} else if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
|
|
if (needsReturnEmptyNode_ || !node->isEmpty()) {
|
|
if (needsReturnEmptyNode_ || !node->isEmpty()) {
|
|
ret = PARTIALMATCH;
|
|
ret = PARTIALMATCH;
|
|
@@ -1156,7 +1212,7 @@ RBTree<T>::find(const isc::dns::Name& target_name,
|
|
}
|
|
}
|
|
node_path.push(node);
|
|
node_path.push(node);
|
|
name = name - node->name_;
|
|
name = name - node->name_;
|
|
- node = node->down_;
|
|
|
|
|
|
+ node = node->getDown();
|
|
} else {
|
|
} else {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -1176,10 +1232,11 @@ RBTree<T>::nextNode(RBTreeNodeChain<T>& node_path) const {
|
|
const RBNode<T>* node = node_path.top();
|
|
const RBNode<T>* node = node_path.top();
|
|
// if node has sub domain, the next domain is the smallest
|
|
// if node has sub domain, the next domain is the smallest
|
|
// domain in sub domain tree
|
|
// domain in sub domain tree
|
|
- if (node->down_ != NULLNODE) {
|
|
|
|
- const RBNode<T>* left_most = node->down_;
|
|
|
|
- while (left_most->left_ != NULLNODE) {
|
|
|
|
- left_most = left_most->left_;
|
|
|
|
|
|
+ const RBNode<T>* down = node->getDown();
|
|
|
|
+ if (down != NULLNODE) {
|
|
|
|
+ const RBNode<T>* left_most = down;
|
|
|
|
+ while (left_most->getLeft() != NULLNODE) {
|
|
|
|
+ left_most = left_most->getLeft();
|
|
}
|
|
}
|
|
node_path.push(left_most);
|
|
node_path.push(left_most);
|
|
return (left_most);
|
|
return (left_most);
|
|
@@ -1247,12 +1304,13 @@ RBTree<T>::previousNode(RBTreeNodeChain<T>& node_path) const {
|
|
while (current != NULLNODE) {
|
|
while (current != NULLNODE) {
|
|
node_path.push(current);
|
|
node_path.push(current);
|
|
// Go a level down and as much right there as possible
|
|
// Go a level down and as much right there as possible
|
|
- current = current->down_;
|
|
|
|
- while (current->right_ != NULLNODE) {
|
|
|
|
|
|
+ current = current->getDown();
|
|
|
|
+ const RBNode<T>* right(NULLNODE);
|
|
|
|
+ while ((right = current->getRight()) != NULLNODE) {
|
|
// A small trick. The current may be NULLNODE, but
|
|
// A small trick. The current may be NULLNODE, but
|
|
// such node has the right_ pointer and it is equal
|
|
// such node has the right_ pointer and it is equal
|
|
// to NULLNODE.
|
|
// to NULLNODE.
|
|
- current = current->right_;
|
|
|
|
|
|
+ current = right;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Now, the one on top of the path is the one we want. We
|
|
// Now, the one on top of the path is the one we want. We
|
|
@@ -1326,12 +1384,14 @@ RBTree<T>::previousNode(RBTreeNodeChain<T>& node_path) const {
|
|
node_path.push(node);
|
|
node_path.push(node);
|
|
|
|
|
|
// Try going as deep as possible, keeping on the right side of the trees
|
|
// Try going as deep as possible, keeping on the right side of the trees
|
|
- while (node->down_ != NULLNODE) {
|
|
|
|
|
|
+ const RBNode<T>* down;
|
|
|
|
+ while ((down = node->getDown()) != NULLNODE) {
|
|
// Move to the tree below
|
|
// Move to the tree below
|
|
- node = node->down_;
|
|
|
|
|
|
+ node = down;
|
|
// And get as much to the right of the tree as possible
|
|
// And get as much to the right of the tree as possible
|
|
- while (node->right_ != NULLNODE) {
|
|
|
|
- node = node->right_;
|
|
|
|
|
|
+ const RBNode<T>* right(NULLNODE);
|
|
|
|
+ while ((right = node->getRight()) != NULLNODE) {
|
|
|
|
+ node = right;
|
|
}
|
|
}
|
|
// Now, we found the right-most node in the sub-tree, we need to
|
|
// Now, we found the right-most node in the sub-tree, we need to
|
|
// include it in the path
|
|
// include it in the path
|
|
@@ -1348,7 +1408,7 @@ typename RBTree<T>::Result
|
|
RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) {
|
|
RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) {
|
|
using namespace helper;
|
|
using namespace helper;
|
|
RBNode<T>* parent = NULLNODE;
|
|
RBNode<T>* parent = NULLNODE;
|
|
- RBNode<T>* current = root_;
|
|
|
|
|
|
+ RBNode<T>* current = root_.get();
|
|
RBNode<T>* up_node = NULLNODE;
|
|
RBNode<T>* up_node = NULLNODE;
|
|
isc::dns::Name name = target_name;
|
|
isc::dns::Name name = target_name;
|
|
|
|
|
|
@@ -1369,14 +1429,14 @@ RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) {
|
|
if (common_label_count == 1 && current->name_.getLength() != 1) {
|
|
if (common_label_count == 1 && current->name_.getLength() != 1) {
|
|
parent = current;
|
|
parent = current;
|
|
order = compare_result.getOrder();
|
|
order = compare_result.getOrder();
|
|
- current = order < 0 ? current->left_ : current->right_;
|
|
|
|
|
|
+ current = order < 0 ? current->getLeft() : current->getRight();
|
|
} else {
|
|
} else {
|
|
// insert sub domain to sub tree
|
|
// insert sub domain to sub tree
|
|
if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
|
|
if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
|
|
parent = NULLNODE;
|
|
parent = NULLNODE;
|
|
up_node = current;
|
|
up_node = current;
|
|
name = name - current->name_;
|
|
name = name - current->name_;
|
|
- current = current->down_;
|
|
|
|
|
|
+ current = current->getDown();
|
|
} else {
|
|
} else {
|
|
// The number of labels in common is fewer
|
|
// The number of labels in common is fewer
|
|
// than the number of labels at the current
|
|
// than the number of labels at the current
|
|
@@ -1392,7 +1452,7 @@ RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- RBNode<T>** current_root = (up_node != NULLNODE) ?
|
|
|
|
|
|
+ typename RBNode<T>::RBNodePtr* current_root = (up_node != NULLNODE) ?
|
|
&(up_node->down_) : &root_;
|
|
&(up_node->down_) : &root_;
|
|
// using auto_ptr here is avoid memory leak in case of exceptoin raised
|
|
// using auto_ptr here is avoid memory leak in case of exceptoin raised
|
|
// after the RBNode creation, if we can make sure no exception will be
|
|
// after the RBNode creation, if we can make sure no exception will be
|
|
@@ -1442,7 +1502,8 @@ RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
|
|
std::swap(node.data_, down_node->data_);
|
|
std::swap(node.data_, down_node->data_);
|
|
std::swap(node.flags_, down_node->flags_);
|
|
std::swap(node.flags_, down_node->flags_);
|
|
|
|
|
|
- down_node->down_ = node.down_;
|
|
|
|
|
|
+ down_node->down_ = node.getDown();
|
|
|
|
+
|
|
node.down_ = down_node.get();
|
|
node.down_ = down_node.get();
|
|
|
|
|
|
// Restore the color of the node (may have gotten changed by the flags swap)
|
|
// Restore the color of the node (may have gotten changed by the flags swap)
|
|
@@ -1461,42 +1522,47 @@ RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
|
|
|
|
|
|
template <typename T>
|
|
template <typename T>
|
|
void
|
|
void
|
|
-RBTree<T>::insertRebalance(RBNode<T>** root, RBNode<T>* node) {
|
|
|
|
-
|
|
|
|
|
|
+RBTree<T>::insertRebalance(typename RBNode<T>::RBNodePtr* root,
|
|
|
|
+ RBNode<T>* node)
|
|
|
|
+{
|
|
RBNode<T>* uncle;
|
|
RBNode<T>* uncle;
|
|
- while (node != *root && node->parent_->getColor() == RBNode<T>::RED) {
|
|
|
|
- if (node->parent_ == node->parent_->parent_->left_) {
|
|
|
|
- uncle = node->parent_->parent_->right_;
|
|
|
|
|
|
+ RBNode<T>* parent;
|
|
|
|
+ while (node != (*root).get() &&
|
|
|
|
+ (parent = node->getParent())->getColor() == RBNode<T>::RED) {
|
|
|
|
+ if (parent == parent->getParent()->getLeft()) {
|
|
|
|
+ uncle = parent->getParent()->getRight();
|
|
|
|
|
|
if (uncle->getColor() == RBNode<T>::RED) {
|
|
if (uncle->getColor() == RBNode<T>::RED) {
|
|
- node->parent_->setColor(RBNode<T>::BLACK);
|
|
|
|
|
|
+ parent->setColor(RBNode<T>::BLACK);
|
|
uncle->setColor(RBNode<T>::BLACK);
|
|
uncle->setColor(RBNode<T>::BLACK);
|
|
- node->parent_->parent_->setColor(RBNode<T>::RED);
|
|
|
|
- node = node->parent_->parent_;
|
|
|
|
|
|
+ parent->getParent()->setColor(RBNode<T>::RED);
|
|
|
|
+ node = parent->getParent();
|
|
} else {
|
|
} else {
|
|
- if (node == node->parent_->right_) {
|
|
|
|
- node = node->parent_;
|
|
|
|
|
|
+ if (node == parent->getRight()) {
|
|
|
|
+ node = parent;
|
|
leftRotate(root, node);
|
|
leftRotate(root, node);
|
|
|
|
+ parent = node->getParent();
|
|
}
|
|
}
|
|
- node->parent_->setColor(RBNode<T>::BLACK);
|
|
|
|
- node->parent_->parent_->setColor(RBNode<T>::RED);
|
|
|
|
- rightRotate(root, node->parent_->parent_);
|
|
|
|
|
|
+ parent->setColor(RBNode<T>::BLACK);
|
|
|
|
+ parent->getParent()->setColor(RBNode<T>::RED);
|
|
|
|
+ rightRotate(root, parent->getParent());
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- uncle = node->parent_->parent_->left_;
|
|
|
|
|
|
+ uncle = parent->getParent()->getLeft();
|
|
if (uncle->getColor() == RBNode<T>::RED) {
|
|
if (uncle->getColor() == RBNode<T>::RED) {
|
|
- node->parent_->setColor(RBNode<T>::BLACK);
|
|
|
|
|
|
+ parent->setColor(RBNode<T>::BLACK);
|
|
uncle->setColor(RBNode<T>::BLACK);
|
|
uncle->setColor(RBNode<T>::BLACK);
|
|
- node->parent_->parent_->setColor(RBNode<T>::RED);
|
|
|
|
- node = node->parent_->parent_;
|
|
|
|
|
|
+ parent->getParent()->setColor(RBNode<T>::RED);
|
|
|
|
+ node = parent->getParent();
|
|
} else {
|
|
} else {
|
|
- if (node == node->parent_->left_) {
|
|
|
|
- node = node->parent_;
|
|
|
|
|
|
+ if (node == parent->getLeft()) {
|
|
|
|
+ node = parent;
|
|
rightRotate(root, node);
|
|
rightRotate(root, node);
|
|
|
|
+ parent = node->getParent();
|
|
}
|
|
}
|
|
- node->parent_->setColor(RBNode<T>::BLACK);
|
|
|
|
- node->parent_->parent_->setColor(RBNode<T>::RED);
|
|
|
|
- leftRotate(root, node->parent_->parent_);
|
|
|
|
|
|
+ parent->setColor(RBNode<T>::BLACK);
|
|
|
|
+ parent->getParent()->setColor(RBNode<T>::RED);
|
|
|
|
+ leftRotate(root, parent->getParent());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1507,24 +1573,26 @@ RBTree<T>::insertRebalance(RBNode<T>** root, RBNode<T>* node) {
|
|
|
|
|
|
template <typename T>
|
|
template <typename T>
|
|
RBNode<T>*
|
|
RBNode<T>*
|
|
-RBTree<T>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
|
|
|
|
- RBNode<T>* right = node->right_;
|
|
|
|
- node->right_ = right->left_;
|
|
|
|
- if (right->left_ != NULLNODE) {
|
|
|
|
- right->left_->parent_ = node;
|
|
|
|
- right->left_->setSubTreeRoot(false);
|
|
|
|
|
|
+RBTree<T>::leftRotate(typename RBNode<T>::RBNodePtr* root, RBNode<T>* node) {
|
|
|
|
+ RBNode<T>* const right = node->getRight();
|
|
|
|
+ RBNode<T>* const rleft = right->getLeft();
|
|
|
|
+ node->right_ = rleft;
|
|
|
|
+ if (rleft != NULLNODE) {
|
|
|
|
+ rleft->parent_ = node;
|
|
|
|
+ rleft->setSubTreeRoot(false);
|
|
} else {
|
|
} else {
|
|
- right->left_->setSubTreeRoot(true);
|
|
|
|
|
|
+ rleft->setSubTreeRoot(true);
|
|
}
|
|
}
|
|
|
|
|
|
- right->parent_ = node->parent_;
|
|
|
|
|
|
+ RBNode<T>* const parent = node->getParent();
|
|
|
|
+ right->parent_ = parent;
|
|
|
|
|
|
- if (node->parent_ != NULLNODE) {
|
|
|
|
|
|
+ if (parent != NULLNODE) {
|
|
right->setSubTreeRoot(false);
|
|
right->setSubTreeRoot(false);
|
|
- if (node == node->parent_->left_) {
|
|
|
|
- node->parent_->left_ = right;
|
|
|
|
|
|
+ if (node == parent->getLeft()) {
|
|
|
|
+ parent->left_ = right;
|
|
} else {
|
|
} else {
|
|
- node->parent_->right_ = right;
|
|
|
|
|
|
+ parent->right_ = right;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
right->setSubTreeRoot(true);
|
|
right->setSubTreeRoot(true);
|
|
@@ -1539,24 +1607,26 @@ RBTree<T>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
|
|
|
|
|
|
template <typename T>
|
|
template <typename T>
|
|
RBNode<T>*
|
|
RBNode<T>*
|
|
-RBTree<T>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
|
|
|
|
- RBNode<T>* left = node->left_;
|
|
|
|
- node->left_ = left->right_;
|
|
|
|
- if (left->right_ != NULLNODE) {
|
|
|
|
- left->right_->parent_ = node;
|
|
|
|
- left->right_->setSubTreeRoot(false);
|
|
|
|
|
|
+RBTree<T>::rightRotate(typename RBNode<T>::RBNodePtr* root, RBNode<T>* node) {
|
|
|
|
+ RBNode<T>* const left = node->getLeft();
|
|
|
|
+ RBNode<T>* const lright = left->getRight();
|
|
|
|
+ node->left_ = lright;
|
|
|
|
+ if (lright != NULLNODE) {
|
|
|
|
+ lright->parent_ = node;
|
|
|
|
+ lright->setSubTreeRoot(false);
|
|
} else {
|
|
} else {
|
|
- left->right_->setSubTreeRoot(true);
|
|
|
|
|
|
+ lright->setSubTreeRoot(false);
|
|
}
|
|
}
|
|
|
|
|
|
- left->parent_ = node->parent_;
|
|
|
|
|
|
+ RBNode<T>* const parent = node->getParent();
|
|
|
|
+ left->parent_ = parent;
|
|
|
|
|
|
- if (node->parent_ != NULLNODE) {
|
|
|
|
|
|
+ if (node->getParent() != NULLNODE) {
|
|
left->setSubTreeRoot(false);
|
|
left->setSubTreeRoot(false);
|
|
- if (node == node->parent_->right_) {
|
|
|
|
- node->parent_->right_ = left;
|
|
|
|
|
|
+ if (node == parent->getRight()) {
|
|
|
|
+ parent->right_ = left;
|
|
} else {
|
|
} else {
|
|
- node->parent_->left_ = left;
|
|
|
|
|
|
+ parent->left_ = left;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
left->setSubTreeRoot(true);
|
|
left->setSubTreeRoot(true);
|
|
@@ -1575,7 +1645,7 @@ void
|
|
RBTree<T>::dumpTree(std::ostream& os, unsigned int depth) const {
|
|
RBTree<T>::dumpTree(std::ostream& os, unsigned int depth) const {
|
|
indent(os, depth);
|
|
indent(os, depth);
|
|
os << "tree has " << node_count_ << " node(s)\n";
|
|
os << "tree has " << node_count_ << " node(s)\n";
|
|
- dumpTreeHelper(os, root_, depth);
|
|
|
|
|
|
+ dumpTreeHelper(os, root_.get(), depth);
|
|
}
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
template <typename T>
|
|
@@ -1600,15 +1670,16 @@ RBTree<T>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
|
|
}
|
|
}
|
|
os << "\n";
|
|
os << "\n";
|
|
|
|
|
|
- if (node->down_ != NULLNODE) {
|
|
|
|
|
|
+ const RBNode<T>* down = node->getDown();
|
|
|
|
+ if (down != NULLNODE) {
|
|
indent(os, depth + 1);
|
|
indent(os, depth + 1);
|
|
os << "begin down from " << node->name_.toText() << "\n";
|
|
os << "begin down from " << node->name_.toText() << "\n";
|
|
- dumpTreeHelper(os, node->down_, depth + 1);
|
|
|
|
|
|
+ dumpTreeHelper(os, down, depth + 1);
|
|
indent(os, depth + 1);
|
|
indent(os, depth + 1);
|
|
os << "end down from " << node->name_.toText() << "\n";
|
|
os << "end down from " << node->name_.toText() << "\n";
|
|
}
|
|
}
|
|
- dumpTreeHelper(os, node->left_, depth + 1);
|
|
|
|
- dumpTreeHelper(os, node->right_, depth + 1);
|
|
|
|
|
|
+ dumpTreeHelper(os, node->getLeft(), depth + 1);
|
|
|
|
+ dumpTreeHelper(os, node->getRight(), depth + 1);
|
|
}
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
template <typename T>
|