enhanced RedBlackTree's iterator

This commit is contained in:
hyung-hwan 2015-03-01 07:34:54 +00:00
parent 6deef2ce4b
commit 8c4921a9b4

View File

@ -49,6 +49,8 @@ public:
BLACK BLACK
}; };
// You must take extreme care not to screw up the whole tree by
// overriding the 'value' variable with a randome value.
T value; // you can use this variable or accessor functions below T value; // you can use this variable or accessor functions below
protected: protected:
@ -92,19 +94,18 @@ public:
const SelfType* getParent () const { return this->parent; } const SelfType* getParent () const { return this->parent; }
SelfType* getLeft () { return this->left; } SelfType* getLeft () { return this->left; }
const SelfType* getLeft () const { return this->left; } const SelfType* getLeftConst () const { return this->left; }
SelfType* getRight () { return this->right; } SelfType* getRight () { return this->right; }
const SelfType* getRight () const { return this->right; } const SelfType* getRightConst () const { return this->right; }
//void setBlack () { this->color = BLACK; }
//void setRed () { this->color = RED; }
//void setParent (SelfType* node) { this->parent = node; }
//void setLeft (SelfType* node) { this->left = node; }
//void setRight (SelfType* node) { this->right = node; }
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 setLeft (SelfType* node) { this->left = node; }
void setRight (SelfType* node) { this->right = node; }
#endif
}; };
template <typename T> template <typename T>
@ -117,86 +118,79 @@ struct RedBlackTreeComparator
} }
}; };
template <typename T, typename COMPARATOR, typename NODE, typename GET_T> template <typename T, typename COMPARATOR, typename GET_NODE, typename GET_T>
class RedBlackTreeIterator class RedBlackTreeIterator
{ {
public: public:
typedef NODE Node; typedef RedBlackTreeNode<T,COMPARATOR> Node;
typedef RedBlackTreeIterator<T,COMPARATOR,NODE,GET_T> SelfType; typedef RedBlackTreeIterator<T,COMPARATOR,GET_NODE,GET_T> SelfType;
typedef Node* (Node::*GetChild) ();
RedBlackTreeIterator (): current (QSE_NULL), previous (QSE_NULL), next_action (0) {} enum Mode
RedBlackTreeIterator (Node* root): current (root)
{ {
ASCENDING,
DESCENDING
};
RedBlackTreeIterator ():
pending_action (0), current (QSE_NULL), previous (QSE_NULL),
get_left (QSE_NULL), get_right (QSE_NULL)
{
}
RedBlackTreeIterator (Node* root, Mode mode): pending_action (0), current (root)
{
QSE_ASSERT (root != QSE_NULL);
this->previous = root->getParent(); this->previous = root->getParent();
if (mode == DESCENDING)
{
this->get_left = &Node::getRight;
this->get_right = &Node::getLeft;
}
else
{
this->get_left = &Node::getLeft;
this->get_right = &Node::getRight;
}
this->__get_next_node (); this->__get_next_node ();
} }
protected: protected:
void __get_next_node () void __get_next_node ()
{ {
int l = 1, r = 0; // TODO: QSE_ASSERT (this->current != QSE_NULL);
while (/*this->current &&*/ this->current->notNil()) while (this->current->notNil())
{ {
if (this->previous == this->current->getParent()) if (this->previous == this->current->getParent())
{ {
/* the previous node is the parent of the current node. /* the previous node is the parent of the current node.
* it indicates that we're going down to the getChild(l) */ * it indicates that we're going down to the getChild(l) */
if (this->current->getChild(l)->notNil()) if ((this->current->*this->get_left)()->notNil())
{ {
/* go to the getChild(l) child */ /* go to the left child */
this->previous = this->current; this->previous = this->current;
this->current = this->current->getChild(l); this->current = (this->current->*this->get_left)();
} }
else else
{ {
this->next_action = 1; this->pending_action = 1;
break; 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)) else if (this->previous == (this->current->*this->get_left)())
{ {
/* the left child has been already traversed */ /* the left child has been already traversed */
this->pending_action = 2;
this->next_action = 2;
break; 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 else
{ {
/* both the left child and the right child have been traversed */ /* both the left child and the right child have been traversed */
QSE_ASSERT (this->previous == this->current->getChild(r)); QSE_ASSERT (this->previous == (this->current->*this->get_right)());
/* just move up to the parent */ /* just move up to the parent */
this->previous = this->current; this->previous = this->current;
this->current = this->current->getParent(); this->current = this->current->getParent();
@ -206,15 +200,13 @@ protected:
void get_next_node () void get_next_node ()
{ {
int l = 1, r = 0; // TODO: if (pending_action == 1)
if (next_action == 1)
{ {
if (this->current->getChild(r)->notNil()) if ((this->current->*this->get_right)()->notNil())
{ {
/* go down to the right node if exists */ /* go down to the right node if exists */
this->previous = this->current; this->previous = this->current;
this->current = this->current->getChild(r); this->current = (this->current->*this->get_right)();
} }
else else
{ {
@ -223,13 +215,13 @@ protected:
this->current = this->current->getParent(); this->current = this->current->getParent();
} }
} }
else if (next_action == 2) else if (pending_action == 2)
{ {
if (this->current->getChild(r)->notNil()) if ((this->current->*this->get_right)()->notNil())
{ {
/* go down to the right node if it exists */ /* go down to the right node if it exists */
this->previous = this->current; this->previous = this->current;
this->current = this->current->getChild(r); this->current = (this->current->*this->get_right)();
} }
else else
{ {
@ -256,6 +248,8 @@ public:
return saved; return saved;
} }
// no operator--
bool isLegit() const bool isLegit() const
{ {
return current->notNil(); return current->notNil();
@ -273,15 +267,19 @@ public:
// no setValue(). // no setValue().
Node* getNode () GET_NODE* getNode ()
{ {
return this->current; return this->current;
} }
protected: protected:
int pending_action;
Node* current; Node* current;
Node* previous; Node* previous;
int next_action; //Node* (Node::*get_left) ();
//Node* (Node::*get_right) ();
GetChild get_left;
GetChild get_right;
}; };
@ -306,9 +304,8 @@ public:
RedBlackTree (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0): Mmged(mmgr), mp (mmgr, QSE_SIZEOF(Node), mpb_size), node_count (0) RedBlackTree (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0): Mmged(mmgr), mp (mmgr, QSE_SIZEOF(Node), mpb_size), node_count (0)
{ {
// initialize nil // create a nil object
this->nil = new(&this->mp) Node(); this->nil = new(&this->mp) Node();
// 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;
@ -327,7 +324,10 @@ public:
RedBlackTree& operator= (const RedBlackTree& rbt) RedBlackTree& operator= (const RedBlackTree& rbt)
{ {
this->clear ();
/* TODO */ /* TODO */
return *this; return *this;
} }
@ -794,16 +794,14 @@ public:
while (this->root->notNil()) this->remove_node (this->root); while (this->root->notNil()) this->remove_node (this->root);
} }
Iterator getIterator () const Iterator getIterator (typename Iterator::Mode mode = Iterator::ASCENDING) const
{ {
return Iterator (this->root); return Iterator (this->root, mode);
} }
void dump (Node* node) ConstIterator getConstIterator (typename ConstIterator::Mode mode = ConstIterator::ASCENDING) const
{ {
printf ("%d %d\n", node->value.getX(), node->value.getY()); return ConstIterator (this->root, mode);
if (node->left->notNil()) this->dump (node->left);
if (node->right->notNil()) this->dump (node->right);
} }
protected: protected:
@ -813,7 +811,6 @@ protected:
qse_size_t node_count; qse_size_t node_count;
Node* nil; // internal node to present nil Node* nil; // internal node to present nil
Node* root; // root node. Node* root; // root node.
}; };