added RedBlackTree::remove()

partially added RedBlackTree::getIterator()
This commit is contained in:
hyung-hwan 2015-03-01 06:29:54 +00:00
parent ecdb510e4b
commit 6deef2ce4b
3 changed files with 521 additions and 170 deletions

View File

@ -80,7 +80,8 @@ protected:
}; };
template <typename T, typename EQUALER, typename NODE, typename GET_T> template <typename T, typename EQUALER, typename NODE, typename GET_T>
class LinkedListIterator { class LinkedListIterator
{
public: public:
friend class LinkedList<T,EQUALER>; friend class LinkedList<T,EQUALER>;
typedef NODE Node; typedef NODE Node;

View File

@ -49,29 +49,25 @@ public:
BLACK BLACK
}; };
enum Child
{
LEFT,
RIGHT
};
T value; // you can use this variable or accessor functions below T value; // you can use this variable or accessor functions below
protected: protected:
Color color; Color color;
SelfType* parent; SelfType* parent;
SelfType* child[2]; // left and right SelfType* left; // left child
SelfType* right; // right child
RedBlackTreeNode() RedBlackTreeNode(): color (BLACK), parent (this), left (this), right (this)
{ {
// no initialization. make sure to initialize member variables later // no initialization on 'value' in this constructor.
} }
RedBlackTreeNode(const T& value, Color color, SelfType* parent, SelfType* left, SelfType* right): RedBlackTreeNode(const T& value, Color color, SelfType* parent, SelfType* left, SelfType* right):
value (value), color (color), parent (parent) value (value), color (color), parent (parent), left (left), right (right)
{ {
this->child[LEFT] = left; QSE_ASSERT (parent != this);
this->child[RIGHT] = right; QSE_ASSERT (left != this);
QSE_ASSERT (right != this);
} }
public: public:
@ -79,34 +75,39 @@ public:
const T& getValue () const { return this->value; } const T& getValue () const { return this->value; }
void setValue (const T& v) { this->value = v; } void setValue (const T& v) { this->value = v; }
bool isNil () const
{
return this->parent == this; // && this->left == this && this->right == this;
}
bool notNil () const
{
return !this->isNil ();
}
bool isBlack () const { return this->color == BLACK; } bool isBlack () const { return this->color == BLACK; }
bool isRed () const { return this->color == RED; } bool isRed () const { return this->color == RED; }
void setBlack () { this->color = BLACK; }
void setRed () { this->color = RED; }
SelfType* getParent () { return this->parent; } SelfType* getParent () { return this->parent; }
const SelfType* getParent () const { return this->parent; } const SelfType* getParent () const { return this->parent; }
SelfType* getLeft () { return this->child[LEFT]; } SelfType* getLeft () { return this->left; }
const SelfType* getLeft () const { return this->child[LEFT]; } const SelfType* getLeft () const { return this->left; }
SelfType* getRight () { return this->child[RIGHT]; } SelfType* getRight () { return this->right; }
const SelfType* getRight () const { return this->child[RIGHT]; } const SelfType* getRight () const { return this->right; }
SelfType* getChild (int idx) { return idx == 0? this->left: this->right; }
#if 0
void setBlack () { this->color = BLACK; }
void setRed () { this->color = RED; }
void setParent (SelfType* node) { this->parent = node; } void setParent (SelfType* node) { this->parent = node; }
void setLeft (SelfType* node) { this->child[LEFT] = node; } void setLeft (SelfType* node) { this->left = node; }
void setRight (SelfType* node) { this->child[RIGHT] = node; } void setRight (SelfType* node) { this->right = node; }
#endif
void setAll (Color color, SelfType* parent, SelfType* left, SelfType* right)
{
this->color = color;
this->parent = parent;
this->child[LEFT] = left;
this->child[RIGHT] = right;
}
}; };
template<typename T> template <typename T>
struct RedBlackTreeComparator struct RedBlackTreeComparator
{ {
int operator() (const T& v1, const T& v2) const int operator() (const T& v1, const T& v2) const
@ -116,12 +117,190 @@ struct RedBlackTreeComparator
} }
}; };
template <typename T, typename COMPARATOR, typename NODE, typename GET_T>
class RedBlackTreeIterator
{
public:
typedef NODE Node;
typedef RedBlackTreeIterator<T,COMPARATOR,NODE,GET_T> SelfType;
RedBlackTreeIterator (): current (QSE_NULL), previous (QSE_NULL), next_action (0) {}
RedBlackTreeIterator (Node* root): current (root)
{
this->previous = root->getParent();
this->__get_next_node ();
}
protected:
void __get_next_node ()
{
int l = 1, r = 0; // TODO:
while (/*this->current &&*/ this->current->notNil())
{
if (this->previous == this->current->getParent())
{
/* the previous node is the parent of the current node.
* it indicates that we're going down to the getChild(l) */
if (this->current->getChild(l)->notNil())
{
/* go to the getChild(l) child */
this->previous = this->current;
this->current = this->current->getChild(l);
}
else
{
this->next_action = 1;
break;
//if (walker (rbt, this->current, ctx) == QSE_RBT_WALK_STOP) break;
#if 0
if (this->current->getChild(r)->notNil())
{
/* go down to the right node if exists */
this->previous = this->current;
this->current = this->current->getChild(r);
}
else
{
/* otherwise, move up to the parent */
this->previous = this->current;
this->current = this->current->getParent();
}
#endif
}
}
else if (this->previous == this->current->getChild(l))
{
/* the left child has been already traversed */
this->next_action = 2;
break;
//if (walker (rbt, this->current, ctx) == QSE_RBT_WALK_STOP) break;
#if 0
if (this->current->getChild(r)->notNil())
{
/* go down to the right node if it exists */
this->previous = this->current;
this->current = this->current->getChild(r);
}
else
{
/* otherwise, move up to the parent */
this->previous = this->current;
this->current = this->current->getParent();
}
#endif
}
else
{
/* both the left child and the right child have been traversed */
QSE_ASSERT (this->previous == this->current->getChild(r));
/* just move up to the parent */
this->previous = this->current;
this->current = this->current->getParent();
}
}
}
void get_next_node ()
{
int l = 1, r = 0; // TODO:
if (next_action == 1)
{
if (this->current->getChild(r)->notNil())
{
/* go down to the right node if exists */
this->previous = this->current;
this->current = this->current->getChild(r);
}
else
{
/* otherwise, move up to the parent */
this->previous = this->current;
this->current = this->current->getParent();
}
}
else if (next_action == 2)
{
if (this->current->getChild(r)->notNil())
{
/* go down to the right node if it exists */
this->previous = this->current;
this->current = this->current->getChild(r);
}
else
{
/* otherwise, move up to the parent */
this->previous = this->current;
this->current = this->current->getParent();
}
}
this->__get_next_node ();
}
public:
SelfType& operator++ () // prefix increment
{
this->get_next_node ();
return *this;
}
SelfType operator++ (int) // postfix increment
{
SelfType saved (*this);
this->get_next_node ();
return saved;
}
bool isLegit() const
{
return current->notNil();
}
GET_T& operator* () // dereference
{
return this->current->getValue();
}
GET_T& getValue ()
{
return this->current->getValue();
}
// no setValue().
Node* getNode ()
{
return this->current;
}
protected:
Node* current;
Node* previous;
int next_action;
};
///
///
/// A node is either red or black.
/// The root is black.
/// All leaves (NIL) are black. (All leaves are same color as the root.)
/// Every red node must have two black child nodes.
/// Every path from a given node to any of its descendant NIL nodes contains the same number of black nodes.
///
template <typename T, typename COMPARATOR = RedBlackTreeComparator<T> > template <typename T, typename COMPARATOR = RedBlackTreeComparator<T> >
class RedBlackTree: public Mmged class RedBlackTree: public Mmged
{ {
public: public:
typedef RedBlackTree<T,COMPARATOR> SelfType; typedef RedBlackTree<T,COMPARATOR> SelfType;
typedef RedBlackTreeNode<T,COMPARATOR> Node; typedef RedBlackTreeNode<T,COMPARATOR> Node;
typedef RedBlackTreeIterator<T,COMPARATOR,Node,T> Iterator;
typedef RedBlackTreeIterator<T,COMPARATOR,const Node,const T> ConstIterator;
typedef RedBlackTreeComparator<T> DefaultComparator; typedef RedBlackTreeComparator<T> DefaultComparator;
@ -129,7 +308,7 @@ public:
{ {
// initialize nil // initialize nil
this->nil = new(&this->mp) Node(); this->nil = new(&this->mp) Node();
this->nil->setAll (Node::BLACK, this->nil, this->nil, this->nil); // this->nil->setAll (Node::BLACK, this->nil, this->nil, this->nil);
// set root to nil // set root to nil
this->root = this->nil; this->root = this->nil;
@ -137,10 +316,13 @@ public:
RedBlackTree (const RedBlackTree& rbt) RedBlackTree (const RedBlackTree& rbt)
{ {
/* TODO */
} }
~RedBlackTree () ~RedBlackTree ()
{ {
this->clear ();
this->dispose_node (this->nil);
} }
RedBlackTree& operator= (const RedBlackTree& rbt) RedBlackTree& operator= (const RedBlackTree& rbt)
@ -169,16 +351,6 @@ public:
return this->node_count <= 0; return this->node_count <= 0;
} }
bool isNil (Node* node) const
{
return node == this->nil;
}
bool notNil (Node* node) const
{
return node != this->nil;
}
Node* getRoot () Node* getRoot ()
{ {
return this->root; return this->root;
@ -190,18 +362,26 @@ public:
} }
protected: protected:
void dispose_node (Node* node)
{
//call the destructor
node->~Node ();
// free the memory
::operator delete (node, &this->mp);
}
Node* find_node (const T& datum) const Node* find_node (const T& datum) const
{ {
Node* node = this->root; Node* node = this->root;
// normal binary tree search // normal binary tree search
while (notNil (node)) while (node->notNil())
{ {
int n = this->comparator (datum, node->value); int n = this->comparator (datum, node->value);
if (n == 0) return node; if (n == 0) return node;
if (n > 0) node = node->getRight(); if (n > 0) node = node->right;
else /* if (n < 0) */ node = node->getLeft(); else /* if (n < 0) */ node = node->left;
} }
return QSE_NULL; return QSE_NULL;
@ -247,33 +427,33 @@ protected:
QSE_ASSERT (pivot != QSE_NULL); QSE_ASSERT (pivot != QSE_NULL);
parent = pivot->getParent(); parent = pivot->parent;
if (leftwise) if (leftwise)
{ {
// y for leftwise rotation // y for leftwise rotation
z = pivot->getRight(); z = pivot->right;
// c1 for leftwise rotation // c1 for leftwise rotation
c = z->getLeft(); c = z->left;
} }
else else
{ {
// x for rightwise rotation // x for rightwise rotation
z = pivot->getLeft(); z = pivot->left;
// c2 for rightwise rotation // c2 for rightwise rotation
c = z->getRight(); c = z->right;
} }
z->setParent (parent); z->parent = parent;
if (notNil (parent)) if (parent->notNil())
{ {
if (parent->getLeft() == pivot) if (parent->left == pivot)
{ {
parent->setLeft (z); parent->left = z;
} }
else else
{ {
QSE_ASSERT (parent->getRight() == pivot); QSE_ASSERT (parent->right == pivot);
parent->setRight (z); parent->right = z;
} }
} }
else else
@ -284,51 +464,61 @@ protected:
if (leftwise) if (leftwise)
{ {
z->setLeft (pivot); z->left = pivot;
pivot->setRight (c); pivot->right = c;
} }
else else
{ {
z->setRight (pivot); z->right = pivot;
pivot->setLeft (c); pivot->left = c;
} }
if (notNil(pivot)) pivot->setParent (z); if (pivot->notNil()) pivot->parent = z;
if (notNil(c)) c->setParent (pivot); if (c->notNil()) c->parent = pivot;
} }
void adjust (Node* node) void rotate_left (Node* pivot)
{
this->rotate (pivot, true);
}
void rotate_right (Node* pivot)
{
this->rotate (pivot, false);
}
void rebalance_for_injection (Node* node)
{ {
while (node != this->root) while (node != this->root)
{ {
Node* tmp, * tmp2, * x_par, * x_par_par; Node* tmp, * tmp2, * x_par, * x_grand_par;
bool leftwise; bool leftwise;
x_par = node->getParent (); x_par = node->parent;
if (x_par->isBlack()) break; if (x_par->color == Node::BLACK) break;
QSE_ASSERT (notNil (x_par->parent)); QSE_ASSERT (x_par->parent->notNil());
x_par_par = x_par->getParent (); x_grand_par = x_par->parent;
if (x_par == x_par_par->getLeft ()) if (x_par == x_grand_par->left)
{ {
tmp = x_par_par->getRight (); tmp = x_grand_par->right;
tmp2 = x_par->getRight (); tmp2 = x_par->right;
leftwise = true; leftwise = true;
} }
else else
{ {
tmp = x_par_par->getLeft (); tmp = x_grand_par->left;
tmp2 = x_par->getLeft (); tmp2 = x_par->left;
leftwise = false; leftwise = false;
} }
if (tmp->isRed ()) if (tmp->color == Node::RED)
{ {
x_par->setBlack (); x_par->color = Node::BLACK;
tmp->setBlack (); tmp->color = Node::BLACK;
x_par_par->setRed (); x_grand_par->color = Node::RED;
node = x_par_par; node = x_grand_par;
} }
else else
{ {
@ -336,17 +526,173 @@ protected:
{ {
node = x_par; node = x_par;
this->rotate (node, leftwise); this->rotate (node, leftwise);
x_par = node->getParent(); x_par = node->parent;
x_par_par = x_par->getParent(); x_grand_par = x_par->parent;
} }
x_par->setBlack(); x_par->color = Node::BLACK;
x_par_par->setRed(); x_grand_par->color = Node::RED;
this->rotate (x_par_par, !leftwise); this->rotate (x_grand_par, !leftwise);
} }
} }
} }
void rebalance_for_removal (Node* node, Node* par)
{
while (node != this->root && node->color == Node::BLACK)
{
Node* tmp;
if (node == par->left)
{
tmp = par->right;
if (tmp->color == Node::RED)
{
tmp->color = Node::BLACK;
par->color = Node::RED;
this->rotate_left (par);
tmp = par->right;
}
if (tmp->left->color == Node::BLACK &&
tmp->right->color == Node::BLACK)
{
if (tmp->notNil()) tmp->color = Node::RED;
node = par;
par = node->parent;
}
else
{
if (tmp->right->color == Node::BLACK)
{
if (tmp->left->notNil())
tmp->left->color = Node::BLACK;
tmp->color = Node::RED;
this->rotate_right (tmp);
tmp = par->right;
}
tmp->color = par->color;
if (par->notNil()) par->color = Node::BLACK;
if (tmp->right->color == Node::RED)
tmp->right->color = Node::BLACK;
this->rotate_left (par);
node = this->root;
}
}
else
{
QSE_ASSERT (node == par->right);
tmp = par->left;
if (tmp->color == Node::RED)
{
tmp->color = Node::BLACK;
par->color = Node::RED;
this->rotate_right (par);
tmp = par->left;
}
if (tmp->left->color == Node::BLACK &&
tmp->right->color == Node::BLACK)
{
if (tmp->notNil()) tmp->color = Node::RED;
node = par;
par = node->parent;
}
else
{
if (tmp->left->color == Node::BLACK)
{
if (tmp->right->notNil())
tmp->right->color = Node::BLACK;
tmp->color = Node::RED;
this->rotate_left (tmp);
tmp = par->left;
}
tmp->color = par->color;
if (par->notNil()) par->color = Node::BLACK;
if (tmp->left->color == Node::RED)
tmp->left->color = Node::BLACK;
this->rotate_right (par);
node = this->root;
}
}
}
node->color = Node::BLACK;
}
void remove_node (Node* node)
{
Node* x, * y, * par;
QSE_ASSERT (node && node->notNil());
if (node->left->isNil() || node->right->isNil())
{
y = node;
}
else
{
/* find a successor with NIL as a child */
y = node->right;
while (y->left->notNil()) y = y->left;
}
x = (y->left->isNil())? y->right: y->left;
par = y->parent;
if (x->notNil()) x->parent = par;
if (par->notNil()) // if (par)
{
if (y == par->left)
par->left = x;
else
par->right = x;
}
else
{
this->root = x;
}
if (y == node)
{
if (y->color == Node::BLACK && x->notNil())
this->rebalance_for_removal (x, par);
this->dispose_node (y);
}
else
{
if (y->color == Node::BLACK && x->notNil())
this->rebalance_for_removal (x, par);
if (node->parent->notNil()) //if (node->parent)
{
if (node->parent->left == node) node->parent->left = y;
if (node->parent->right == node) node->parent->right = y;
}
else
{
this->root = y;
}
y->parent = node->parent;
y->left = node->left;
y->right = node->right;
y->color = node->color;
if (node->left->parent == node) node->left->parent = y;
if (node->right->parent == node) node->right->parent = y;
this->dispose_node (node);
}
this->node_count--;
}
public: public:
Node* search (const T& datum) Node* search (const T& datum)
@ -364,41 +710,27 @@ public:
Node* x_cur = this->root; Node* x_cur = this->root;
Node* x_par = this->nil; Node* x_par = this->nil;
while (notNil (x_cur)) while (x_cur->notNil())
{ {
int n = this->comparator (datum, x_cur->value); int n = this->comparator (datum, x_cur->value);
if (n == 0) if (n == 0)
{ {
#if 0 if (injected) *injected = false;
switch (opt) if (mode <= -1) return QSE_NULL; // return failure
{ if (mode >= 1) x_cur->value = datum;
case UPSERT: return x_cur;
case UPDATE:
return change_pair_val (rbt, x_cur, vptr, vlen);
case ENSERT:
/* return existing pair */
return x_cur;
case INSERT:
/* return failure */
return QSE_NULL;
}
#endif
} }
x_par = x_cur; x_par = x_cur;
if (n > 0) x_cur = x_cur->getRight (); if (n > 0) x_cur = x_cur->right;
else /* if (n < 0) */ x_cur = x_cur->getLeft (); else /* if (n < 0) */ x_cur = x_cur->left;
} }
//if (opt == UPDATE) return QSE_NULL;
Node* x_new = new(&this->mp) Node (datum, Node::RED, this->nil, this->nil, this->nil); Node* x_new = new(&this->mp) Node (datum, Node::RED, this->nil, this->nil, this->nil);
if (isNil (x_par)) if (x_par->isNil())
{ {
QSE_ASSERT (isNil (this->root)); QSE_ASSERT (this->root->isNil());
this->root = x_new; this->root = x_new;
} }
else else
@ -406,22 +738,23 @@ public:
int n = this->comparator (datum, x_par->value); int n = this->comparator (datum, x_par->value);
if (n > 0) if (n > 0)
{ {
QSE_ASSERT (isNil (x_par->getRight ())); QSE_ASSERT (x_par->right->isNil());
x_par->setRight (x_new); x_par->right = x_new;
} }
else else
{ {
QSE_ASSERT (isNil (x_par->getLeft ())); QSE_ASSERT (x_par->left->isNil());
x_par->setLeft (x_new); x_par->left = x_new;
} }
x_new->setParent (x_par); x_new->parent = x_par;
this->adjust (x_new); this->rebalance_for_injection (x_new);
} }
this->root->setBlack (); this->root->color = Node::BLACK;
this->node_count++; this->node_count++;
if (injected) *injected = true; // indicate that a new node has been injected
return x_new; return x_new;
} }
@ -440,20 +773,37 @@ public:
return this->inject (datum, 1, QSE_NULL); return this->inject (datum, 1, QSE_NULL);
} }
#if 0
Node* update (const T& datum) Node* update (const T& datum)
{ {
Node* node = this->find_node (datum); Node* node = this->find_node (datum);
if (node) node->value = datum; if (node) node->value = datum;
return node; return node;
} }
#endif
int remove (const T& datum)
{
Node* node = this->find_node (datum);
if (node == QSE_NULL) return -1;
this->remove_node (node);
return 0;
}
void clear (bool clear_mpool = false)
{
while (this->root->notNil()) this->remove_node (this->root);
}
Iterator getIterator () const
{
return Iterator (this->root);
}
void dump (Node* node) void dump (Node* node)
{ {
printf ("%d %d\n", node->value.getX(), node->value.getY()); printf ("%d %d\n", node->value.getX(), node->value.getY());
if (notNil(node->getLeft())) dump (node->getLeft()); if (node->left->notNil()) this->dump (node->left);
if (notNil(node->getRight())) dump (node->getRight()); if (node->right->notNil()) this->dump (node->right);
} }
protected: protected: