added RedBlackTree::remove()
partially added RedBlackTree::getIterator()
This commit is contained in:
parent
ecdb510e4b
commit
6deef2ce4b
@ -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;
|
||||||
|
@ -36,7 +36,7 @@ QSE_BEGIN_NAMESPACE(QSE)
|
|||||||
|
|
||||||
template <typename T, typename COMPARATOR> class RedBlackTree;
|
template <typename T, typename COMPARATOR> class RedBlackTree;
|
||||||
|
|
||||||
template <typename T, typename COMPARATOR>
|
template <typename T, typename COMPARATOR>
|
||||||
class RedBlackTreeNode
|
class RedBlackTreeNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -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,49 +75,232 @@ 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
|
||||||
{
|
{
|
||||||
return (v1 > v2)? 1:
|
return (v1 > v2)? 1:
|
||||||
(v1 < v2)? -1: 0;
|
(v1 < v2)? -1: 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
@ -159,27 +341,17 @@ public:
|
|||||||
return this->mp;
|
return this->mp;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_size_t getSize () const
|
qse_size_t getSize () const
|
||||||
{
|
{
|
||||||
return this->node_count;
|
return this->node_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEmpty () const
|
bool isEmpty () const
|
||||||
{
|
{
|
||||||
return this->node_count <= 0;
|
return this->node_count <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNil (Node* node) const
|
Node* getRoot ()
|
||||||
{
|
|
||||||
return node == this->nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool notNil (Node* node) const
|
|
||||||
{
|
|
||||||
return node != this->nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
@ -211,11 +391,11 @@ protected:
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* == leftwise rotation
|
* == leftwise rotation
|
||||||
* move the pivot pair down to the poistion of the pivot's original
|
* move the pivot pair down to the poistion of the pivot's original
|
||||||
* left child(x). move the pivot's right child(y) to the pivot's original
|
* left child(x). move the pivot's right child(y) to the pivot's original
|
||||||
* position. as 'c1' is between 'y' and 'pivot', move it to the right
|
* position. as 'c1' is between 'y' and 'pivot', move it to the right
|
||||||
* of the new pivot position.
|
* of the new pivot position.
|
||||||
* parent parent
|
* parent parent
|
||||||
* | | (left or right?) | |
|
* | | (left or right?) | |
|
||||||
* pivot y
|
* pivot y
|
||||||
* / \ / \
|
* / \ / \
|
||||||
@ -224,56 +404,56 @@ protected:
|
|||||||
* c1 c2 x c1
|
* c1 c2 x c1
|
||||||
*
|
*
|
||||||
* == rightwise rotation
|
* == rightwise rotation
|
||||||
* move the pivot pair down to the poistion of the pivot's original
|
* move the pivot pair down to the poistion of the pivot's original
|
||||||
* right child(y). move the pivot's left child(x) to the pivot's original
|
* right child(y). move the pivot's left child(x) to the pivot's original
|
||||||
* position. as 'c2' is between 'x' and 'pivot', move it to the left
|
* position. as 'c2' is between 'x' and 'pivot', move it to the left
|
||||||
* of the new pivot position.
|
* of the new pivot position.
|
||||||
*
|
*
|
||||||
* parent parent
|
* parent parent
|
||||||
* | | (left or right?) | |
|
* | | (left or right?) | |
|
||||||
* pivot x
|
* pivot x
|
||||||
* / \ / \
|
* / \ / \
|
||||||
* x y =====> c1 pivot
|
* x y =====> c1 pivot
|
||||||
* / \ / \
|
* / \ / \
|
||||||
* c1 c2 c2 y
|
* c1 c2 c2 y
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* the actual implementation here resolves the pivot's relationship to
|
* the actual implementation here resolves the pivot's relationship to
|
||||||
* its parent by comparaing pointers as it is not known if the pivot pair
|
* its parent by comparaing pointers as it is not known if the pivot pair
|
||||||
* is the left child or the right child of its parent,
|
* is the left child or the right child of its parent,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Node* parent, * z, * c;
|
Node* parent, * z, * c;
|
||||||
|
|
||||||
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:
|
||||||
@ -461,7 +811,7 @@ protected:
|
|||||||
COMPARATOR comparator;
|
COMPARATOR comparator;
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -95,7 +95,7 @@ QSE_INLINE pair_t* qse_rbt_allocpair (
|
|||||||
KPTR(n) = n + 1;
|
KPTR(n) = n + 1;
|
||||||
if (kptr) QSE_MEMCPY (KPTR(n), kptr, KTOB(rbt,klen));
|
if (kptr) QSE_MEMCPY (KPTR(n), kptr, KTOB(rbt,klen));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
KPTR(n) = kcop (rbt, kptr, klen);
|
KPTR(n) = kcop (rbt, kptr, klen);
|
||||||
if (KPTR(n) == QSE_NULL)
|
if (KPTR(n) == QSE_NULL)
|
||||||
@ -113,11 +113,11 @@ QSE_INLINE pair_t* qse_rbt_allocpair (
|
|||||||
else if (vcop == QSE_RBT_COPIER_INLINE)
|
else if (vcop == QSE_RBT_COPIER_INLINE)
|
||||||
{
|
{
|
||||||
VPTR(n) = n + 1;
|
VPTR(n) = n + 1;
|
||||||
if (kcop == QSE_RBT_COPIER_INLINE)
|
if (kcop == QSE_RBT_COPIER_INLINE)
|
||||||
VPTR(n) = (byte_t*)VPTR(n) + KTOB(rbt,klen);
|
VPTR(n) = (byte_t*)VPTR(n) + KTOB(rbt,klen);
|
||||||
if (vptr) QSE_MEMCPY (VPTR(n), vptr, VTOB(rbt,vlen));
|
if (vptr) QSE_MEMCPY (VPTR(n), vptr, VTOB(rbt,vlen));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VPTR(n) = vcop (rbt, vptr, vlen);
|
VPTR(n) = vcop (rbt, vptr, vlen);
|
||||||
if (VPTR(n) != QSE_NULL)
|
if (VPTR(n) != QSE_NULL)
|
||||||
@ -134,7 +134,7 @@ QSE_INLINE pair_t* qse_rbt_allocpair (
|
|||||||
|
|
||||||
QSE_INLINE void qse_rbt_freepair (rbt_t* rbt, pair_t* pair)
|
QSE_INLINE void qse_rbt_freepair (rbt_t* rbt, pair_t* pair)
|
||||||
{
|
{
|
||||||
if (rbt->style->freeer[QSE_RBT_KEY] != QSE_NULL)
|
if (rbt->style->freeer[QSE_RBT_KEY] != QSE_NULL)
|
||||||
rbt->style->freeer[QSE_RBT_KEY] (rbt, KPTR(pair), KLEN(pair));
|
rbt->style->freeer[QSE_RBT_KEY] (rbt, KPTR(pair), KLEN(pair));
|
||||||
if (rbt->style->freeer[QSE_RBT_VAL] != QSE_NULL)
|
if (rbt->style->freeer[QSE_RBT_VAL] != QSE_NULL)
|
||||||
rbt->style->freeer[QSE_RBT_VAL] (rbt, VPTR(pair), VLEN(pair));
|
rbt->style->freeer[QSE_RBT_VAL] (rbt, VPTR(pair), VLEN(pair));
|
||||||
@ -235,7 +235,7 @@ int qse_rbt_init (rbt_t* rbt, mmgr_t* mmgr, int kscale, int vscale)
|
|||||||
rbt->size = 0;
|
rbt->size = 0;
|
||||||
|
|
||||||
rbt->style = &style[0];
|
rbt->style = &style[0];
|
||||||
|
|
||||||
/* self-initializing nil */
|
/* self-initializing nil */
|
||||||
QSE_MEMSET(&rbt->xnil, 0, QSE_SIZEOF(rbt->xnil));
|
QSE_MEMSET(&rbt->xnil, 0, QSE_SIZEOF(rbt->xnil));
|
||||||
rbt->xnil.color = QSE_RBT_BLACK;
|
rbt->xnil.color = QSE_RBT_BLACK;
|
||||||
@ -299,11 +299,11 @@ static void rotate (rbt_t* rbt, pair_t* pivot, int leftwise)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* == leftwise rotation
|
* == leftwise rotation
|
||||||
* move the pivot pair down to the poistion of the pivot's original
|
* move the pivot pair down to the poistion of the pivot's original
|
||||||
* left child(x). move the pivot's right child(y) to the pivot's original
|
* left child(x). move the pivot's right child(y) to the pivot's original
|
||||||
* position. as 'c1' is between 'y' and 'pivot', move it to the right
|
* position. as 'c1' is between 'y' and 'pivot', move it to the right
|
||||||
* of the new pivot position.
|
* of the new pivot position.
|
||||||
* parent parent
|
* parent parent
|
||||||
* | | (left or right?) | |
|
* | | (left or right?) | |
|
||||||
* pivot y
|
* pivot y
|
||||||
* / \ / \
|
* / \ / \
|
||||||
@ -312,23 +312,23 @@ static void rotate (rbt_t* rbt, pair_t* pivot, int leftwise)
|
|||||||
* c1 c2 x c1
|
* c1 c2 x c1
|
||||||
*
|
*
|
||||||
* == rightwise rotation
|
* == rightwise rotation
|
||||||
* move the pivot pair down to the poistion of the pivot's original
|
* move the pivot pair down to the poistion of the pivot's original
|
||||||
* right child(y). move the pivot's left child(x) to the pivot's original
|
* right child(y). move the pivot's left child(x) to the pivot's original
|
||||||
* position. as 'c2' is between 'x' and 'pivot', move it to the left
|
* position. as 'c2' is between 'x' and 'pivot', move it to the left
|
||||||
* of the new pivot position.
|
* of the new pivot position.
|
||||||
*
|
*
|
||||||
* parent parent
|
* parent parent
|
||||||
* | | (left or right?) | |
|
* | | (left or right?) | |
|
||||||
* pivot x
|
* pivot x
|
||||||
* / \ / \
|
* / \ / \
|
||||||
* x y =====> c1 pivot
|
* x y =====> c1 pivot
|
||||||
* / \ / \
|
* / \ / \
|
||||||
* c1 c2 c2 y
|
* c1 c2 c2 y
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* the actual implementation here resolves the pivot's relationship to
|
* the actual implementation here resolves the pivot's relationship to
|
||||||
* its parent by comparaing pointers as it is not known if the pivot pair
|
* its parent by comparaing pointers as it is not known if the pivot pair
|
||||||
* is the left child or the right child of its parent,
|
* is the left child or the right child of its parent,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pair_t* parent, * z, * c;
|
pair_t* parent, * z, * c;
|
||||||
@ -349,9 +349,9 @@ static void rotate (rbt_t* rbt, pair_t* pivot, int leftwise)
|
|||||||
|
|
||||||
parent = pivot->parent;
|
parent = pivot->parent;
|
||||||
/* y for leftwise rotation, x for rightwise rotation */
|
/* y for leftwise rotation, x for rightwise rotation */
|
||||||
z = pivot->child[cid1];
|
z = pivot->child[cid1];
|
||||||
/* c1 for leftwise rotation, c2 for rightwise rotation */
|
/* c1 for leftwise rotation, c2 for rightwise rotation */
|
||||||
c = z->child[cid2];
|
c = z->child[cid2];
|
||||||
|
|
||||||
z->parent = parent;
|
z->parent = parent;
|
||||||
if (parent)
|
if (parent)
|
||||||
@ -391,7 +391,7 @@ static void adjust (rbt_t* rbt, pair_t* pair)
|
|||||||
|
|
||||||
QSE_ASSERT (x_par->parent != QSE_NULL);
|
QSE_ASSERT (x_par->parent != QSE_NULL);
|
||||||
|
|
||||||
if (x_par == x_par->parent->child[LEFT])
|
if (x_par == x_par->parent->child[LEFT])
|
||||||
{
|
{
|
||||||
tmp = x_par->parent->child[RIGHT];
|
tmp = x_par->parent->child[RIGHT];
|
||||||
tmp2 = x_par->child[RIGHT];
|
tmp2 = x_par->child[RIGHT];
|
||||||
@ -430,10 +430,10 @@ static void adjust (rbt_t* rbt, pair_t* pair)
|
|||||||
static pair_t* change_pair_val (
|
static pair_t* change_pair_val (
|
||||||
rbt_t* rbt, pair_t* pair, void* vptr, size_t vlen)
|
rbt_t* rbt, pair_t* pair, void* vptr, size_t vlen)
|
||||||
{
|
{
|
||||||
if (VPTR(pair) == vptr && VLEN(pair) == vlen)
|
if (VPTR(pair) == vptr && VLEN(pair) == vlen)
|
||||||
{
|
{
|
||||||
/* if the old value and the new value are the same,
|
/* if the old value and the new value are the same,
|
||||||
* it just calls the handler for this condition.
|
* it just calls the handler for this condition.
|
||||||
* No value replacement occurs. */
|
* No value replacement occurs. */
|
||||||
if (rbt->style->keeper != QSE_NULL)
|
if (rbt->style->keeper != QSE_NULL)
|
||||||
{
|
{
|
||||||
@ -461,7 +461,7 @@ static pair_t* change_pair_val (
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* need to reconstruct the pair */
|
/* need to reconstruct the pair */
|
||||||
pair_t* p = qse_rbt_allocpair (rbt,
|
pair_t* p = qse_rbt_allocpair (rbt,
|
||||||
KPTR(pair), KLEN(pair),
|
KPTR(pair), KLEN(pair),
|
||||||
vptr, vlen);
|
vptr, vlen);
|
||||||
if (p == QSE_NULL) return QSE_NULL;
|
if (p == QSE_NULL) return QSE_NULL;
|
||||||
@ -477,7 +477,7 @@ static pair_t* change_pair_val (
|
|||||||
{
|
{
|
||||||
pair->parent->left = p;
|
pair->parent->left = p;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QSE_ASSERT (pair->parent->right == pair);
|
QSE_ASSERT (pair->parent->right == pair);
|
||||||
pair->parent->right = p;
|
pair->parent->right = p;
|
||||||
@ -492,7 +492,7 @@ static pair_t* change_pair_val (
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
void* nvptr = vcop (rbt, vptr, vlen);
|
void* nvptr = vcop (rbt, vptr, vlen);
|
||||||
if (nvptr == QSE_NULL) return QSE_NULL;
|
if (nvptr == QSE_NULL) return QSE_NULL;
|
||||||
@ -501,7 +501,7 @@ static pair_t* change_pair_val (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* free up the old value */
|
/* free up the old value */
|
||||||
if (rbt->style->freeer[QSE_RBT_VAL] != QSE_NULL)
|
if (rbt->style->freeer[QSE_RBT_VAL] != QSE_NULL)
|
||||||
{
|
{
|
||||||
rbt->style->freeer[QSE_RBT_VAL] (rbt, ovptr, ovlen);
|
rbt->style->freeer[QSE_RBT_VAL] (rbt, ovptr, ovlen);
|
||||||
}
|
}
|
||||||
@ -515,12 +515,12 @@ static pair_t* insert (
|
|||||||
{
|
{
|
||||||
pair_t* x_cur = rbt->root;
|
pair_t* x_cur = rbt->root;
|
||||||
pair_t* x_par = QSE_NULL;
|
pair_t* x_par = QSE_NULL;
|
||||||
pair_t* x_new;
|
pair_t* x_new;
|
||||||
|
|
||||||
while (!IS_NIL(rbt,x_cur))
|
while (!IS_NIL(rbt,x_cur))
|
||||||
{
|
{
|
||||||
int n = rbt->style->comper (rbt, kptr, klen, KPTR(x_cur), KLEN(x_cur));
|
int n = rbt->style->comper (rbt, kptr, klen, KPTR(x_cur), KLEN(x_cur));
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
switch (opt)
|
switch (opt)
|
||||||
{
|
{
|
||||||
@ -530,7 +530,7 @@ static pair_t* insert (
|
|||||||
|
|
||||||
case ENSERT:
|
case ENSERT:
|
||||||
/* return existing pair */
|
/* return existing pair */
|
||||||
return x_cur;
|
return x_cur;
|
||||||
|
|
||||||
case INSERT:
|
case INSERT:
|
||||||
/* return failure */
|
/* return failure */
|
||||||
@ -609,18 +609,18 @@ pair_t* qse_rbt_cbsert (
|
|||||||
{
|
{
|
||||||
pair_t* x_cur = rbt->root;
|
pair_t* x_cur = rbt->root;
|
||||||
pair_t* x_par = QSE_NULL;
|
pair_t* x_par = QSE_NULL;
|
||||||
pair_t* x_new;
|
pair_t* x_new;
|
||||||
|
|
||||||
while (!IS_NIL(rbt,x_cur))
|
while (!IS_NIL(rbt,x_cur))
|
||||||
{
|
{
|
||||||
int n = rbt->style->comper (rbt, kptr, klen, KPTR(x_cur), KLEN(x_cur));
|
int n = rbt->style->comper (rbt, kptr, klen, KPTR(x_cur), KLEN(x_cur));
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
/* back up the contents of the current pair
|
/* back up the contents of the current pair
|
||||||
* in case it is reallocated */
|
* in case it is reallocated */
|
||||||
pair_t tmp;
|
pair_t tmp;
|
||||||
|
|
||||||
tmp = *x_cur;
|
tmp = *x_cur;
|
||||||
|
|
||||||
/* call the callback function to manipulate the pair */
|
/* call the callback function to manipulate the pair */
|
||||||
x_new = cbserter (rbt, x_cur, kptr, klen, ctx);
|
x_new = cbserter (rbt, x_cur, kptr, klen, ctx);
|
||||||
@ -647,7 +647,7 @@ pair_t* qse_rbt_cbsert (
|
|||||||
{
|
{
|
||||||
tmp.parent->left = x_new;
|
tmp.parent->left = x_new;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QSE_ASSERT (tmp.parent->right == x_cur);
|
QSE_ASSERT (tmp.parent->right == x_cur);
|
||||||
tmp.parent->right = x_new;
|
tmp.parent->right = x_new;
|
||||||
@ -730,7 +730,7 @@ static void adjust_for_delete (rbt_t* rbt, pair_t* pair, pair_t* par)
|
|||||||
{
|
{
|
||||||
if (tmp->right->color == QSE_RBT_BLACK)
|
if (tmp->right->color == QSE_RBT_BLACK)
|
||||||
{
|
{
|
||||||
if (!IS_NIL(rbt,tmp->left))
|
if (!IS_NIL(rbt,tmp->left))
|
||||||
tmp->left->color = QSE_RBT_BLACK;
|
tmp->left->color = QSE_RBT_BLACK;
|
||||||
tmp->color = QSE_RBT_RED;
|
tmp->color = QSE_RBT_RED;
|
||||||
rotate_right (rbt, tmp);
|
rotate_right (rbt, tmp);
|
||||||
@ -946,7 +946,7 @@ static QSE_INLINE void walk (
|
|||||||
{
|
{
|
||||||
/* otherwise, move up to the parent */
|
/* otherwise, move up to the parent */
|
||||||
prev = x_cur;
|
prev = x_cur;
|
||||||
x_cur = x_cur->parent;
|
x_cur = x_cur->parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -958,15 +958,15 @@ static QSE_INLINE void walk (
|
|||||||
|
|
||||||
if (!IS_NIL(rbt,x_cur->child[r]))
|
if (!IS_NIL(rbt,x_cur->child[r]))
|
||||||
{
|
{
|
||||||
/* go down to the right node if it exists */
|
/* go down to the right node if it exists */
|
||||||
prev = x_cur;
|
prev = x_cur;
|
||||||
x_cur = x_cur->child[r];
|
x_cur = x_cur->child[r];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* otherwise, move up to the parent */
|
/* otherwise, move up to the parent */
|
||||||
prev = x_cur;
|
prev = x_cur;
|
||||||
x_cur = x_cur->parent;
|
x_cur = x_cur->parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user