template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> * ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_predecessor (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x) const { ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_tree_predecessor"); if (x == 0) return 0; if (x->left ()) return RB_tree_maximum (x->left ()); ACE_RB_Tree_Node<EXT_ID, INT_ID> *y = x->parent (); while ((y) && (x == y->left ())) { x = y; y = y->parent (); } return y; }
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (const EXT_ID &k, INT_ID &i) { ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (const EXT_ID &k, INT_ID &i)"); // Find a matching node, if there is one. ACE_RB_Tree_Node<EXT_ID, INT_ID> *z; RB_SearchResult result = LEFT; z = find_node (k, result); // If there is a matching node: remove and destroy it. if (z && result == EXACT) { // Return the internal id stored in the deleted node. i = z->item (); return -1 == this->remove_i (z) ? -1 : 1; } // No matching node was found: return 0. return 0; }
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>:: dump_node_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> &node) const { #if defined (ACE_HAS_DUMP) const char * color_str = (node.color () == ACE_RB_Tree_Node_Base::RED) ? "RED" : "BLACK"; ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" color=[%s]\n"), color_str)); #else /* !ACE_HAS_DUMP */ ACE_UNUSED_ARG (node); #endif /* ACE_HAS_DUMP */ }
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> ACE_RB_Tree_Node<EXT_ID, INT_ID> * ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_node (const EXT_ID &k, ACE_RB_Tree_Base::RB_SearchResult &result) { ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::find_node"); // Start at the root. ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = root_; while (current) { // While there are more nodes to examine. if (this->lessthan (current->key (), k)) { // If the search key is greater than the current node's key. if (current->right ()) // If the right subtree is not empty, search to the right. current = current->right (); else { // If the right subtree is empty, we're done searching, // and are positioned to the left of the insertion point. result = LEFT; break; } } else if (this->lessthan (k, current->key ())) { // Else if the search key is less than the current node's key. if (current->left ()) // If the left subtree is not empty, search to the left. current = current->left (); else { // If the left subtree is empty, we're done searching, // and are positioned to the right of the insertion point. result = RIGHT; break; } } else { // If the keys match exactly, we're done as well. result = EXACT; break; } } return current; }
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z) { ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z)"); // Delete the node and reorganize the tree to satisfy the Red-Black // properties. ACE_RB_Tree_Node<EXT_ID, INT_ID> *x; ACE_RB_Tree_Node<EXT_ID, INT_ID> *y; ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent; if (z->left () && z->right ()) y = RB_tree_successor (z); else y = z; if (!y) return -1; if (y->left ()) x = y->left (); else x = y->right (); parent = y->parent (); if (x) { x->parent (parent); } if (parent) { if (y == parent->left ()) parent->left (x); else parent->right (x); } else this->root_ = x; if (y != z) { // Replace node z with node y, since y's pointer may well be // held externally, and be linked with y's key and item. // We will end up deleting the old unlinked, node z. ACE_RB_Tree_Node<EXT_ID, INT_ID> *zParent = z->parent (); ACE_RB_Tree_Node<EXT_ID, INT_ID> *zLeftChild = z->left (); ACE_RB_Tree_Node<EXT_ID, INT_ID> *zRightChild = z->right (); if (zParent) { if (z == zParent->left ()) { zParent->left (y); } else { zParent->right (y); } } else { this->root_ = y; } y->parent (zParent); if (zLeftChild) { zLeftChild->parent (y); } y->left (zLeftChild); if (zRightChild) { zRightChild->parent (y); } y->right (zRightChild); if (parent == z) { parent = y; } ACE_RB_Tree_Node_Base::RB_Tree_Node_Color yColor = y->color (); y->color (z->color ()); z->color (yColor); //Reassign the y pointer to z because the node that y points to will be //deleted y = z; } // CLR pp. 263 says that nil nodes are implicitly colored BLACK if (!y || y->color () == ACE_RB_Tree_Node_Base::BLACK) RB_delete_fixup (x, parent); y->parent (0); y->right (0); y->left (0); ACE_DES_FREE_TEMPLATE2 (y, this->allocator_->free, ACE_RB_Tree_Node, EXT_ID, INT_ID); --this->current_size_; return 0; }
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i (const EXT_ID &k, const INT_ID &t, ACE_RB_Tree_Node<EXT_ID, INT_ID> *&entry) { ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::insert_i"); // Find the closest matching node, if there is one. RB_SearchResult result = LEFT; ACE_RB_Tree_Node<EXT_ID, INT_ID> *current = find_node (k, result); if (current) { // If the keys match, just return a pointer to the node's item. if (result == EXACT) { entry = current; return 1; } // Otherwise if we're to the left of the insertion // point, insert into the right subtree. else if (result == LEFT) { if (current->right ()) { // If there is already a right subtree, complain. ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("\nright subtree already present in ") ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")), -1); } else { // The right subtree is empty: insert new node there. ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0; ACE_NEW_MALLOC_RETURN (tmp, (reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*> (this->allocator_->malloc (sizeof (*tmp)))), (ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t), -1); current->right (tmp); // If the node was successfully inserted, set its parent, rebalance // the tree, color the root black, and return a pointer to the // inserted item. entry = current->right (); current->right ()->parent (current); RB_rebalance (current->right ()); this->root_->color (ACE_RB_Tree_Node_Base::BLACK); ++this->current_size_; return 0; } } // Otherwise, we're to the right of the insertion point, so // insert into the left subtree. else // (result == RIGHT) { if (current->left ()) // If there is already a left subtree, complain. ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("\nleft subtree already present in ") ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::insert_i\n")), -1); else { // The left subtree is empty: insert new node there. ACE_RB_Tree_Node<EXT_ID, INT_ID> *tmp = 0; ACE_NEW_MALLOC_RETURN (tmp, (reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*> (this->allocator_->malloc (sizeof (*tmp)))), (ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t), -1); current->left (tmp); // If the node was successfully inserted, set its // parent, rebalance the tree, color the root black, and // return a pointer to the inserted item. entry = current->left (); current->left ()->parent (current); RB_rebalance (current->left ()); this->root_->color (ACE_RB_Tree_Node_Base::BLACK); ++this->current_size_; return 0; } } } else { // The tree is empty: insert at the root and color the root black. ACE_NEW_MALLOC_RETURN (this->root_, (reinterpret_cast<ACE_RB_Tree_Node<EXT_ID, INT_ID>*> (this->allocator_->malloc (sizeof (ACE_RB_Tree_Node<EXT_ID, INT_ID>)))), (ACE_RB_Tree_Node<EXT_ID, INT_ID>) (k, t), -1); this->root_->color (ACE_RB_Tree_Node_Base::BLACK); ++this->current_size_; entry = this->root_; return 0; } }
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rebalance (ACE_RB_Tree_Node<EXT_ID, INT_ID> * x) { ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_rebalance"); ACE_RB_Tree_Node<EXT_ID, INT_ID> *y = 0; while (x && x->parent () && x->parent ()->color () == ACE_RB_Tree_Node_Base::RED) { if (! x->parent ()->parent ()) { // If we got here, something is drastically wrong! ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("\nerror: parent's parent is null in ") ACE_TEXT ("ACE_RB_Tree<EXT_ID, INT_ID>::RB_rebalance\n"))); return; } if (x->parent () == x->parent ()->parent ()->left ()) { y = x->parent ()->parent ()->right (); if (y && y->color () == ACE_RB_Tree_Node_Base::RED) { // Handle case 1 (see CLR book, pp. 269). x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK); y->color (ACE_RB_Tree_Node_Base::BLACK); x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED); x = x->parent ()->parent (); } else { if (x == x->parent ()->right ()) { // Transform case 2 into case 3 (see CLR book, pp. 269). x = x->parent (); RB_rotate_left (x); } // Handle case 3 (see CLR book, pp. 269). x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK); x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED); RB_rotate_right (x->parent ()->parent ()); } } else { y = x->parent ()->parent ()->left (); if (y && y->color () == ACE_RB_Tree_Node_Base::RED) { // Handle case 1 (see CLR book, pp. 269). x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK); y->color (ACE_RB_Tree_Node_Base::BLACK); x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED); x = x->parent ()->parent (); } else { if (x == x->parent ()->left ()) { // Transform case 2 into case 3 (see CLR book, pp. 269). x = x->parent (); RB_rotate_right (x); } // Handle case 3 (see CLR book, pp. 269). x->parent ()->color (ACE_RB_Tree_Node_Base::BLACK); x->parent ()->parent ()->color (ACE_RB_Tree_Node_Base::RED); RB_rotate_left (x->parent ()->parent ()); } } } }
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> void ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>:: RB_delete_fixup (ACE_RB_Tree_Node<EXT_ID, INT_ID> *x, ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent) { ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::RB_delete_fixup"); while (x != this->root_ && (!x || x->color () == ACE_RB_Tree_Node_Base::BLACK)) { if (x == parent->left ()) { ACE_RB_Tree_Node<EXT_ID, INT_ID> *w = parent->right (); if (w && w->color () == ACE_RB_Tree_Node_Base::RED) { w->color (ACE_RB_Tree_Node_Base::BLACK); parent->color (ACE_RB_Tree_Node_Base::RED); RB_rotate_left (parent); w = parent->right (); } // CLR pp. 263 says that nil nodes are implicitly colored BLACK if (w && (!w->left () || w->left ()->color () == ACE_RB_Tree_Node_Base::BLACK) && (!w->right () || w->right ()->color () == ACE_RB_Tree_Node_Base::BLACK)) { w->color (ACE_RB_Tree_Node_Base::RED); x = parent; parent = x->parent (); } else { // CLR pp. 263 says that nil nodes are implicitly colored BLACK if (w && (!w->right () || w->right ()->color () == ACE_RB_Tree_Node_Base::BLACK)) { if (w->left ()) w->left ()->color (ACE_RB_Tree_Node_Base::BLACK); w->color (ACE_RB_Tree_Node_Base::RED); RB_rotate_right (w); w = parent->right (); } if (w) { w->color (parent->color ()); if (w->right ()) w->right ()->color (ACE_RB_Tree_Node_Base::BLACK); } parent->color (ACE_RB_Tree_Node_Base::BLACK); RB_rotate_left (parent); x = root_; } } else { ACE_RB_Tree_Node<EXT_ID, INT_ID> *w = parent->left (); if (w && w->color () == ACE_RB_Tree_Node_Base::RED) { w->color (ACE_RB_Tree_Node_Base::BLACK); parent->color (ACE_RB_Tree_Node_Base::RED); RB_rotate_right (parent); w = parent->left (); } // CLR pp. 263 says that nil nodes are implicitly colored BLACK if (w && (!w->left () || w->left ()->color () == ACE_RB_Tree_Node_Base::BLACK) && (!w->right () || w->right ()->color () == ACE_RB_Tree_Node_Base::BLACK)) { w->color (ACE_RB_Tree_Node_Base::RED); x = parent; parent = x->parent (); } else { // CLR pp. 263 says that nil nodes are implicitly colored BLACK if (w && (!w->left () || w->left ()->color () == ACE_RB_Tree_Node_Base::BLACK)) { w->color (ACE_RB_Tree_Node_Base::RED); if (w->right ()) w->right ()->color (ACE_RB_Tree_Node_Base::BLACK); RB_rotate_left (w); w = parent->left (); } if (w) { w->color (parent->color ()); if (w->left ()) w->left ()->color (ACE_RB_Tree_Node_Base::BLACK); } parent->color (ACE_RB_Tree_Node_Base::BLACK); RB_rotate_right (parent); x = root_; } } } if (x) x->color (ACE_RB_Tree_Node_Base::BLACK); }
template <class EXT_ID, class INT_ID, class COMPARE_KEYS, class ACE_LOCK> int ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z) { ACE_TRACE ("ACE_RB_Tree<EXT_ID, INT_ID, COMPARE_KEYS, ACE_LOCK>::remove_i (ACE_RB_Tree_Node<EXT_ID, INT_ID> *z)"); // Delete the node and reorganize the tree to satisfy the Red-Black // properties. ACE_RB_Tree_Node<EXT_ID, INT_ID> *x; ACE_RB_Tree_Node<EXT_ID, INT_ID> *y; ACE_RB_Tree_Node<EXT_ID, INT_ID> *parent; if (z->left () && z->right ()) y = RB_tree_successor (z); else y = z; if (!y) return -1; if (y->left ()) x = y->left (); else x = y->right (); parent = y->parent (); if (x) { x->parent (parent); } if (parent) { if (y == parent->left ()) parent->left (x); else parent->right (x); } else this->root_ = x; if (y != z) { // Copy the elements of y into z. z->key () = y->key (); z->item () = y->item (); } // CLR pp. 263 says that nil nodes are implicitly colored BLACK if (!y || y->color () == ACE_RB_Tree_Node_Base::BLACK) RB_delete_fixup (x, parent); y->parent (0); y->right (0); y->left (0); ACE_DES_FREE_TEMPLATE2 (y, this->allocator_->free, ACE_RB_Tree_Node, EXT_ID, INT_ID); --this->current_size_; return 0; }