// 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_