diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-03-09 13:19:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-03-09 13:20:02 +0000 |
commit | 58daab21cd043e1dc37024a7f99b396788372918 (patch) | |
tree | 96771e43bb69f7c1c2b0b4f7374cb74d7866d0cb /ml/dlib/dlib/binary_search_tree/binary_search_tree_kernel_2.h | |
parent | Releasing debian version 1.43.2-1. (diff) | |
download | netdata-58daab21cd043e1dc37024a7f99b396788372918.tar.xz netdata-58daab21cd043e1dc37024a7f99b396788372918.zip |
Merging upstream version 1.44.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ml/dlib/dlib/binary_search_tree/binary_search_tree_kernel_2.h')
-rw-r--r-- | ml/dlib/dlib/binary_search_tree/binary_search_tree_kernel_2.h | 1897 |
1 files changed, 1897 insertions, 0 deletions
diff --git a/ml/dlib/dlib/binary_search_tree/binary_search_tree_kernel_2.h b/ml/dlib/dlib/binary_search_tree/binary_search_tree_kernel_2.h new file mode 100644 index 000000000..098d38c2e --- /dev/null +++ b/ml/dlib/dlib/binary_search_tree/binary_search_tree_kernel_2.h @@ -0,0 +1,1897 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BINARY_SEARCH_TREE_KERNEl_2_ +#define DLIB_BINARY_SEARCH_TREE_KERNEl_2_ + +#include "binary_search_tree_kernel_abstract.h" +#include "../algs.h" +#include "../interfaces/map_pair.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" +#include <functional> + +namespace dlib +{ + + template < + typename domain, + typename range, + typename mem_manager, + typename compare = std::less<domain> + > + class binary_search_tree_kernel_2 : public enumerable<map_pair<domain,range> >, + public asc_pair_remover<domain,range,compare> + { + + /*! + INITIAL VALUE + NIL == pointer to a node that represents a leaf + tree_size == 0 + tree_root == NIL + at_start == true + current_element == 0 + + + CONVENTION + current_element_valid() == (current_element != 0) + if (current_element_valid()) then + element() == current_element->d and current_element->r + at_start_ == at_start() + + + tree_size == size() + + NIL == pointer to a node that represents a leaf + + if (tree_size != 0) + tree_root == pointer to the root node of the binary search tree + else + tree_root == NIL + + tree_root->color == black + Every leaf is black and all leafs are the NIL node. + The number of black nodes in any path from the root to a leaf is the + same. + + for all nodes: + { + - left points to the left subtree or NIL if there is no left subtree + - right points to the right subtree or NIL if there is no right + subtree + - parent points to the parent node or NIL if the node is the root + - ordering of nodes is determined by comparing each node's d member + - all elements in a left subtree are <= the node + - all elements in a right subtree are >= the node + - color == red or black + - if (color == red) + - the node's children are black + } + + !*/ + + class node + { + public: + node* left; + node* right; + node* parent; + domain d; + range r; + char color; + }; + + class mpair : public map_pair<domain,range> + { + public: + const domain* d; + range* r; + + const domain& key( + ) const { return *d; } + + const range& value( + ) const { return *r; } + + range& value( + ) { return *r; } + }; + + + const static char red = 0; + const static char black = 1; + + + public: + + typedef domain domain_type; + typedef range range_type; + typedef compare compare_type; + typedef mem_manager mem_manager_type; + + binary_search_tree_kernel_2( + ) : + NIL(pool.allocate()), + tree_size(0), + tree_root(NIL), + current_element(0), + at_start_(true) + { + NIL->color = black; + NIL->left = 0; + NIL->right = 0; + NIL->parent = 0; + } + + virtual ~binary_search_tree_kernel_2( + ); + + inline void clear( + ); + + inline short height ( + ) const; + + inline unsigned long count ( + const domain& d + ) const; + + inline void add ( + domain& d, + range& r + ); + + void remove ( + const domain& d, + domain& d_copy, + range& r + ); + + void destroy ( + const domain& d + ); + + void remove_any ( + domain& d, + range& r + ); + + inline const range* operator[] ( + const domain& item + ) const; + + inline range* operator[] ( + const domain& item + ); + + inline void swap ( + binary_search_tree_kernel_2& item + ); + + // functions from the enumerable interface + inline size_t size ( + ) const; + + bool at_start ( + ) const; + + inline void reset ( + ) const; + + bool current_element_valid ( + ) const; + + const map_pair<domain,range>& element ( + ) const; + + map_pair<domain,range>& element ( + ); + + bool move_next ( + ) const; + + void remove_last_in_order ( + domain& d, + range& r + ); + + void remove_current_element ( + domain& d, + range& r + ); + + void position_enumerator ( + const domain& d + ) const; + + private: + + inline void rotate_left ( + node* t + ); + /*! + requires + - t != NIL + - t->right != NIL + ensures + - performs a left rotation around t and its right child + !*/ + + inline void rotate_right ( + node* t + ); + /*! + requires + - t != NIL + - t->left != NIL + ensures + - performs a right rotation around t and its left child + !*/ + + inline void double_rotate_right ( + node* t + ); + /*! + requires + - t != NIL + - t->left != NIL + - t->left->right != NIL + - double_rotate_right() is only called in fix_after_add() + ensures + - performs a left rotation around t->left + - then performs a right rotation around t + !*/ + + inline void double_rotate_left ( + node* t + ); + /*! + requires + - t != NIL + - t->right != NIL + - t->right->left != NIL + - double_rotate_left() is only called in fix_after_add() + ensures + - performs a right rotation around t->right + - then performs a left rotation around t + !*/ + + void remove_biggest_element_in_tree ( + node* t, + domain& d, + range& r + ); + /*! + requires + - t != NIL (i.e. there must be something in the tree to remove) + ensures + - the biggest node in t has been removed + - the biggest node element in t has been put into #d and #r + - #t is still a binary search tree + !*/ + + bool remove_least_element_in_tree ( + node* t, + domain& d, + range& r + ); + /*! + requires + - t != NIL (i.e. there must be something in the tree to remove) + ensures + - the least node in t has been removed + - the least node element in t has been put into #d and #r + - #t is still a binary search tree + - if (the node that was removed was the one pointed to by current_element) then + - returns true + - else + - returns false + !*/ + + void add_to_tree ( + node* t, + domain& d, + range& r + ); + /*! + requires + - t != NIL + ensures + - d and r are now in #t + - there is a mapping from d to r in #t + - #d and #r have initial values for their types + - #t is still a binary search tree + !*/ + + void remove_from_tree ( + node* t, + const domain& d, + domain& d_copy, + range& r + ); + /*! + requires + - return_reference(t,d) != 0 + ensures + - #d_copy is equivalent to d + - the first element in t equivalent to d that is encountered when searching down the tree + from t has been removed and swapped into #d_copy. Also, the associated range element + has been removed and swapped into #r. + - if (the node that got removed wasn't current_element) then + - adjusts the current_element pointer if the data in the node that it points to gets moved. + - else + - the value of current_element is now invalid + - #t is still a binary search tree + !*/ + + void remove_from_tree ( + node* t, + const domain& d + ); + /*! + requires + - return_reference(t,d) != 0 + ensures + - an element in t equivalent to d has been removed + - #t is still a binary search tree + !*/ + + const range* return_reference ( + const node* t, + const domain& d + ) const; + /*! + ensures + - if (there is a domain element equivalent to d in t) then + - returns a pointer to the element in the range equivalent to d + - else + - returns 0 + !*/ + + range* return_reference ( + node* t, + const domain& d + ); + /*! + ensures + - if (there is a domain element equivalent to d in t) then + - returns a pointer to the element in the range equivalent to d + - else + - returns 0 + !*/ + + void fix_after_add ( + node* t + ); + /*! + requires + - t == pointer to the node just added + - t->color == red + - t->parent != NIL (t must not be the root) + - fix_after_add() is only called after a new node has been added + to t + ensures + - fixes any deviations from the CONVENTION caused by adding a node + !*/ + + void fix_after_remove ( + node* t + ); + /*! + requires + - t == pointer to the only child of the node that was spliced out + - fix_after_remove() is only called after a node has been removed + from t + - the color of the spliced out node was black + ensures + - fixes any deviations from the CONVENTION causes by removing a node + !*/ + + + short tree_height ( + node* t + ) const; + /*! + ensures + - returns the number of nodes in the longest path from the root of the + tree to a leaf + !*/ + + void delete_tree ( + node* t + ); + /*! + requires + - t == root of binary search tree + - t != NIL + ensures + - deletes all nodes in t except for NIL + !*/ + + unsigned long get_count ( + const domain& item, + node* tree_root + ) const; + /*! + requires + - tree_root == the root of a binary search tree or NIL + ensures + - if (tree_root == NIL) then + - returns 0 + - else + - returns the number of elements in tree_root that are + equivalent to item + !*/ + + + + // data members + typename mem_manager::template rebind<node>::other pool; + node* NIL; + unsigned long tree_size; + node* tree_root; + mutable node* current_element; + mutable bool at_start_; + mutable mpair p; + compare comp; + + + + // restricted functions + binary_search_tree_kernel_2(binary_search_tree_kernel_2&); + binary_search_tree_kernel_2& operator=(binary_search_tree_kernel_2&); + + + }; + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + inline void swap ( + binary_search_tree_kernel_2<domain,range,mem_manager,compare>& a, + binary_search_tree_kernel_2<domain,range,mem_manager,compare>& b + ) { a.swap(b); } + + + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void deserialize ( + binary_search_tree_kernel_2<domain,range,mem_manager,compare>& item, + std::istream& in + ) + { + try + { + item.clear(); + unsigned long size; + deserialize(size,in); + domain d; + range r; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + deserialize(r,in); + item.add(d,r); + } + } + catch (serialization_error e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type binary_search_tree_kernel_2"); + } + } + + + + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + ~binary_search_tree_kernel_2 ( + ) + { + if (tree_root != NIL) + delete_tree(tree_root); + pool.deallocate(NIL); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + clear ( + ) + { + if (tree_size > 0) + { + delete_tree(tree_root); + tree_root = NIL; + tree_size = 0; + } + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + size_t binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + size ( + ) const + { + return tree_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + short binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + height ( + ) const + { + return tree_height(tree_root); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + unsigned long binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + count ( + const domain& item + ) const + { + return get_count(item,tree_root); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + add ( + domain& d, + range& r + ) + { + if (tree_size == 0) + { + tree_root = pool.allocate(); + tree_root->color = black; + tree_root->left = NIL; + tree_root->right = NIL; + tree_root->parent = NIL; + exchange(tree_root->d,d); + exchange(tree_root->r,r); + } + else + { + add_to_tree(tree_root,d,r); + } + ++tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + remove ( + const domain& d, + domain& d_copy, + range& r + ) + { + remove_from_tree(tree_root,d,d_copy,r); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + destroy ( + const domain& item + ) + { + remove_from_tree(tree_root,item); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + remove_any ( + domain& d, + range& r + ) + { + remove_least_element_in_tree(tree_root,d,r); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + range* binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + operator[] ( + const domain& d + ) + { + return return_reference(tree_root,d); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + const range* binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + operator[] ( + const domain& d + ) const + { + return return_reference(tree_root,d); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + swap ( + binary_search_tree_kernel_2<domain,range,mem_manager,compare>& item + ) + { + pool.swap(item.pool); + + exchange(p,item.p); + exchange(comp,item.comp); + + node* tree_root_temp = item.tree_root; + unsigned long tree_size_temp = item.tree_size; + node* const NIL_temp = item.NIL; + node* current_element_temp = item.current_element; + bool at_start_temp = item.at_start_; + + item.tree_root = tree_root; + item.tree_size = tree_size; + item.NIL = NIL; + item.current_element = current_element; + item.at_start_ = at_start_; + + tree_root = tree_root_temp; + tree_size = tree_size_temp; + NIL = NIL_temp; + current_element = current_element_temp; + at_start_ = at_start_temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + remove_last_in_order ( + domain& d, + range& r + ) + { + remove_biggest_element_in_tree(tree_root,d,r); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + remove_current_element ( + domain& d, + range& r + ) + { + node* t = current_element; + move_next(); + remove_from_tree(t,t->d,d,r); + --tree_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + position_enumerator ( + const domain& d + ) const + { + // clear the enumerator state and make sure the stack is empty + reset(); + at_start_ = false; + node* t = tree_root; + node* parent = NIL; + bool went_left = false; + while (t != NIL) + { + if ( comp(d , t->d )) + { + // if item is on the left then look in left + parent = t; + t = t->left; + went_left = true; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + parent = t; + t = t->right; + went_left = false; + } + else + { + current_element = t; + return; + } + } + + // if we didn't find any matches but there might be something after the + // d in this tree. + if (parent != NIL) + { + current_element = parent; + // if we went left from this node then this node is the next + // biggest. + if (went_left) + { + return; + } + else + { + move_next(); + } + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // enumerable function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + at_start ( + ) const + { + return at_start_; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + reset ( + ) const + { + at_start_ = true; + current_element = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + current_element_valid ( + ) const + { + return (current_element != 0); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + const map_pair<domain,range>& binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + element ( + ) const + { + p.d = &(current_element->d); + p.r = &(current_element->r); + return p; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + map_pair<domain,range>& binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + element ( + ) + { + p.d = &(current_element->d); + p.r = &(current_element->r); + return p; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + move_next ( + ) const + { + // if we haven't started iterating yet + if (at_start_) + { + at_start_ = false; + if (tree_size == 0) + { + return false; + } + else + { + // find the first element in the tree + current_element = tree_root; + node* temp = current_element->left; + while (temp != NIL) + { + current_element = temp; + temp = current_element->left; + } + return true; + } + } + else + { + if (current_element == 0) + { + return false; + } + else + { + bool went_up; // true if we went up the tree from a child node to parent + bool from_left = false; // true if we went up and were coming from a left child node + // find the next element in the tree + if (current_element->right != NIL) + { + // go right and down + current_element = current_element->right; + went_up = false; + } + else + { + went_up = true; + node* parent = current_element->parent; + if (parent == NIL) + { + // in this case we have iterated over all the element of the tree + current_element = 0; + return false; + } + + from_left = (parent->left == current_element); + // go up to parent + current_element = parent; + } + + + while (true) + { + if (went_up) + { + if (from_left) + { + // in this case we have found the next node + break; + } + else + { + // we should go up + node* parent = current_element->parent; + from_left = (parent->left == current_element); + current_element = parent; + if (current_element == NIL) + { + // in this case we have iterated over all the elements + // in the tree + current_element = 0; + return false; + } + } + } + else + { + // we just went down to a child node + if (current_element->left != NIL) + { + // go left + went_up = false; + current_element = current_element->left; + } + else + { + // if there is no left child then we have found the next node + break; + } + } + } + + return true; + } + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // private member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + delete_tree ( + node* t + ) + { + if (t->left != NIL) + delete_tree(t->left); + if (t->right != NIL) + delete_tree(t->right); + pool.deallocate(t); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + rotate_left ( + node* t + ) + { + + // perform the rotation + node* temp = t->right; + t->right = temp->left; + if (temp->left != NIL) + temp->left->parent = t; + temp->left = t; + temp->parent = t->parent; + + + if (t == tree_root) + tree_root = temp; + else + { + // if t was on the left + if (t->parent->left == t) + t->parent->left = temp; + else + t->parent->right = temp; + } + + t->parent = temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + rotate_right ( + node* t + ) + { + // perform the rotation + node* temp = t->left; + t->left = temp->right; + if (temp->right != NIL) + temp->right->parent = t; + temp->right = t; + temp->parent = t->parent; + + if (t == tree_root) + tree_root = temp; + else + { + // if t is a left child + if (t->parent->left == t) + t->parent->left = temp; + else + t->parent->right = temp; + } + + t->parent = temp; + } + + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + double_rotate_right ( + node* t + ) + { + + // preform the rotation + node& temp = *(t->left->right); + t->left = temp.right; + temp.right->parent = t; + temp.left->parent = temp.parent; + temp.parent->right = temp.left; + temp.parent->parent = &temp; + temp.right = t; + temp.left = temp.parent; + temp.parent = t->parent; + + + if (tree_root == t) + tree_root = &temp; + else + { + // t is a left child + if (t->parent->left == t) + t->parent->left = &temp; + else + t->parent->right = &temp; + } + t->parent = &temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + double_rotate_left ( + node* t + ) + { + + + // preform the rotation + node& temp = *(t->right->left); + t->right = temp.left; + temp.left->parent = t; + temp.right->parent = temp.parent; + temp.parent->left = temp.right; + temp.parent->parent = &temp; + temp.left = t; + temp.right = temp.parent; + temp.parent = t->parent; + + + if (tree_root == t) + tree_root = &temp; + else + { + // t is a left child + if (t->parent->left == t) + t->parent->left = &temp; + else + t->parent->right = &temp; + } + t->parent = &temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + remove_biggest_element_in_tree ( + node* t, + domain& d, + range& r + ) + { + + node* next = t->right; + node* child; // the child node of the one we will slice out + + if (next == NIL) + { + // need to determine if t is a right or left child + if (t->parent->right == t) + child = t->parent->right = t->left; + else + child = t->parent->left = t->left; + + // update tree_root if necessary + if (t == tree_root) + tree_root = child; + } + else + { + // find the least node + do + { + t = next; + next = next->right; + } while (next != NIL); + // t is a right child + child = t->parent->right = t->left; + + } + + // swap the item from this node into d and r + exchange(d,t->d); + exchange(r,t->r); + + // plug hole right by removing this node + child->parent = t->parent; + + // keep the red-black properties true + if (t->color == black) + fix_after_remove(child); + + // free the memory for this removed node + pool.deallocate(t); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + remove_least_element_in_tree ( + node* t, + domain& d, + range& r + ) + { + + node* next = t->left; + node* child; // the child node of the one we will slice out + + if (next == NIL) + { + // need to determine if t is a left or right child + if (t->parent->left == t) + child = t->parent->left = t->right; + else + child = t->parent->right = t->right; + + // update tree_root if necessary + if (t == tree_root) + tree_root = child; + } + else + { + // find the least node + do + { + t = next; + next = next->left; + } while (next != NIL); + // t is a left child + child = t->parent->left = t->right; + + } + + // swap the item from this node into d and r + exchange(d,t->d); + exchange(r,t->r); + + // plug hole left by removing this node + child->parent = t->parent; + + // keep the red-black properties true + if (t->color == black) + fix_after_remove(child); + + bool rvalue = (t == current_element); + // free the memory for this removed node + pool.deallocate(t); + return rvalue; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + add_to_tree ( + node* t, + domain& d, + range& r + ) + { + // parent of the current node + node* parent; + + // find a place to add node + while (true) + { + parent = t; + // if item should be put on the left then go left + if (comp(d , t->d)) + { + t = t->left; + if (t == NIL) + { + t = parent->left = pool.allocate(); + break; + } + } + // if item should be put on the right then go right + else + { + t = t->right; + if (t == NIL) + { + t = parent->right = pool.allocate(); + break; + } + } + } + + // t is now the node where we will add item and + // parent is the parent of t + + t->parent = parent; + t->left = NIL; + t->right = NIL; + t->color = red; + exchange(t->d,d); + exchange(t->r,r); + + + // keep the red-black properties true + fix_after_add(t); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + remove_from_tree ( + node* t, + const domain& d, + domain& d_copy, + range& r + ) + { + while (true) + { + if ( comp(d , t->d) ) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // found the node we want to remove + + // swap out the item into d_copy and r + exchange(d_copy,t->d); + exchange(r,t->r); + + if (t->left == NIL) + { + // if there is no left subtree + + node* parent = t->parent; + + // plug hole with right subtree + + + // if t is on the left + if (parent->left == t) + parent->left = t->right; + else + parent->right = t->right; + t->right->parent = parent; + + // update tree_root if necessary + if (t == tree_root) + tree_root = t->right; + + if (t->color == black) + fix_after_remove(t->right); + + // delete old node + pool.deallocate(t); + } + else if (t->right == NIL) + { + // if there is no right subtree + + node* parent = t->parent; + + // plug hole with left subtree + if (parent->left == t) + parent->left = t->left; + else + parent->right = t->left; + t->left->parent = parent; + + // update tree_root if necessary + if (t == tree_root) + tree_root = t->left; + + if (t->color == black) + fix_after_remove(t->left); + + // delete old node + pool.deallocate(t); + } + else + { + // if there is both a left and right subtree + // get an element to fill this node now that its been swapped into + // item_copy + if (remove_least_element_in_tree(t->right,t->d,t->r)) + { + // the node removed was the one pointed to by current_element so we + // need to update it so that it points to the right spot. + current_element = t; + } + } + + // quit loop + break; + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + remove_from_tree ( + node* t, + const domain& d + ) + { + while (true) + { + if ( comp(d , t->d) ) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // found the node we want to remove + + + if (t->left == NIL) + { + // if there is no left subtree + + node* parent = t->parent; + + // plug hole with right subtree + + + if (parent->left == t) + parent->left = t->right; + else + parent->right = t->right; + t->right->parent = parent; + + // update tree_root if necessary + if (t == tree_root) + tree_root = t->right; + + if (t->color == black) + fix_after_remove(t->right); + + // delete old node + pool.deallocate(t); + } + else if (t->right == NIL) + { + // if there is no right subtree + + node* parent = t->parent; + + // plug hole with left subtree + if (parent->left == t) + parent->left = t->left; + else + parent->right = t->left; + t->left->parent = parent; + + // update tree_root if necessary + if (t == tree_root) + tree_root = t->left; + + if (t->color == black) + fix_after_remove(t->left); + + // delete old node + pool.deallocate(t); + } + else + { + // if there is both a left and right subtree + // get an element to fill this node now that its been swapped into + // item_copy + remove_least_element_in_tree(t->right,t->d,t->r); + + } + + // quit loop + break; + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + range* binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + return_reference ( + node* t, + const domain& d + ) + { + while (t != NIL) + { + if ( comp(d , t->d )) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // if it's found then return a reference to it + return &(t->r); + } + } + return 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + const range* binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + return_reference ( + const node* t, + const domain& d + ) const + { + while (t != NIL) + { + if ( comp(d , t->d) ) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // if it's found then return a reference to it + return &(t->r); + } + } + return 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + fix_after_add ( + node* t + ) + { + + while (t->parent->color == red) + { + node& grandparent = *(t->parent->parent); + + // if both t's parent and its sibling are red + if (grandparent.left->color == grandparent.right->color) + { + grandparent.color = red; + grandparent.left->color = black; + grandparent.right->color = black; + t = &grandparent; + } + else + { + // if t is a left child + if (t == t->parent->left) + { + // if t's parent is a left child + if (t->parent == grandparent.left) + { + grandparent.color = red; + grandparent.left->color = black; + rotate_right(&grandparent); + } + // if t's parent is a right child + else + { + t->color = black; + grandparent.color = red; + double_rotate_left(&grandparent); + } + } + // if t is a right child + else + { + // if t's parent is a left child + if (t->parent == grandparent.left) + { + t->color = black; + grandparent.color = red; + double_rotate_right(&grandparent); + } + // if t's parent is a right child + else + { + grandparent.color = red; + grandparent.right->color = black; + rotate_left(&grandparent); + } + } + break; + } + } + tree_root->color = black; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + fix_after_remove ( + node* t + ) + { + + while (t != tree_root && t->color == black) + { + if (t->parent->left == t) + { + node* sibling = t->parent->right; + if (sibling->color == red) + { + sibling->color = black; + t->parent->color = red; + rotate_left(t->parent); + sibling = t->parent->right; + } + + if (sibling->left->color == black && sibling->right->color == black) + { + sibling->color = red; + t = t->parent; + } + else + { + if (sibling->right->color == black) + { + sibling->left->color = black; + sibling->color = red; + rotate_right(sibling); + sibling = t->parent->right; + } + + sibling->color = t->parent->color; + t->parent->color = black; + sibling->right->color = black; + rotate_left(t->parent); + t = tree_root; + + } + + + } + else + { + + node* sibling = t->parent->left; + if (sibling->color == red) + { + sibling->color = black; + t->parent->color = red; + rotate_right(t->parent); + sibling = t->parent->left; + } + + if (sibling->left->color == black && sibling->right->color == black) + { + sibling->color = red; + t = t->parent; + } + else + { + if (sibling->left->color == black) + { + sibling->right->color = black; + sibling->color = red; + rotate_left(sibling); + sibling = t->parent->left; + } + + sibling->color = t->parent->color; + t->parent->color = black; + sibling->left->color = black; + rotate_right(t->parent); + t = tree_root; + + } + + + } + + } + t->color = black; + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + short binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + tree_height ( + node* t + ) const + { + if (t == NIL) + return 0; + + short height1 = tree_height(t->left); + short height2 = tree_height(t->right); + if (height1 > height2) + return height1 + 1; + else + return height2 + 1; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + unsigned long binary_search_tree_kernel_2<domain,range,mem_manager,compare>:: + get_count ( + const domain& d, + node* tree_root + ) const + { + if (tree_root != NIL) + { + if (comp(d , tree_root->d)) + { + // go left + return get_count(d,tree_root->left); + } + else if (comp(tree_root->d , d)) + { + // go right + return get_count(d,tree_root->right); + } + else + { + // go left and right to look for more matches + return get_count(d,tree_root->left) + + get_count(d,tree_root->right) + + 1; + } + } + return 0; + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_2_ + |