123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940 |
|
/*******************************************************************************
copyright: Copyright (c) 2008 Kris Bell. All rights reserved
license: BSD style: $(LICENSE)
version: Apr 2008: Initial release
authors: Kris, tsalm
Since: 0.99.7
Based upon Doug Lea's Java collection package
*******************************************************************************/
module tango.util.container.RedBlack;
import tango.util.container.model.IContainer;
alias int AttributeDummy;
/*******************************************************************************
RedBlack implements basic capabilities of Red-Black trees,
an efficient kind of balanced binary tree. The particular
algorithms used are adaptations of those in Corman,
Lieserson, and Rivest's <EM>Introduction to Algorithms</EM>.
This class was inspired by (and code cross-checked with) a
similar class by Chuck McManis. The implementations of
rebalancings during insertion and deletion are
a little trickier than those versions since they
don't swap Cell contents or use special dummy nilnodes.
Doug Lea
*******************************************************************************/
struct RedBlack (V, A = AttributeDummy)
{
alias RedBlack!(V, A) Type;
alias Type *Ref;
enum : bool {RED = false, BLACK = true}
/**
* Pointer to left child
**/
package Ref left;
/**
* Pointer to right child
**/
package Ref right;
/**
* Pointer to parent (null if root)
**/
package Ref parent;
package V value;
static if (!is(typeof(A) == AttributeDummy))
{
A attribute;
}
/**
* The node color (RED, BLACK)
**/
package bool color;
static if (!is(typeof(A) == AttributeDummy))
{
final Ref set (V v, A a)
{
attribute = a;
return set (v);
}
}
/**
* Make a new Cell with given value, null links, and BLACK color.
* Normally only called to establish a new root.
**/
final Ref set (V v)
{
value = v;
left = null;
right = null;
parent = null;
color = BLACK;
return &this;
}
/**
* Return a new Ref with same value and color as self,
* but with null links. (Since it is never OK to have
* multiple identical links in a RB tree.)
**/
protected Ref dup (scope Ref delegate() alloc)
{
static if (is(typeof(A) == AttributeDummy))
auto t = alloc().set (value);
else
auto t = alloc().set (value, attribute);
t.color = color;
return t;
}
/**
* See_Also: tango.util.collection.model.View.View.checkImplementation.
**/
public void checkImplementation ()
{
// It's too hard to check the property that every simple
// path from node to leaf has same number of black nodes.
// So restrict to the following
assert(parent is null ||
&this is parent.left ||
&this is parent.right);
assert(left is null ||
&this is left.parent);
assert(right is null ||
&this is right.parent);
assert(color is BLACK ||
(colorOf(left) is BLACK) && (colorOf(right) is BLACK));
if (left !is null)
left.checkImplementation();
if (right !is null)
right.checkImplementation();
}
/**
* Return the minimum value of the current (sub)tree
**/
Ref leftmost ()
{
auto p = &this;
for ( ; p.left; p = p.left) {}
return p;
}
/**
* Return the maximum value of the current (sub)tree
**/
Ref rightmost ()
{
auto p = &this;
for ( ; p.right; p = p.right) {}
return p;
}
/**
* Return the root (parentless node) of the tree
**/
Ref root ()
{
auto p = &this;
for ( ; p.parent; p = p.parent) {}
return p;
}
/**
* Return true if node is a root (i.e., has a null parent)
**/
bool isRoot ()
{
return parent is null;
}
/**
* Return the inorder successor, or null if no such
**/
Ref successor ()
{
if (right)
return right.leftmost;
auto p = parent;
auto ch = &this;
while (p && ch is p.right)
{
ch = p;
p = p.parent;
}
return p;
}
/**
* Return the inorder predecessor, or null if no such
**/
Ref predecessor ()
{
if (left)
return left.rightmost;
auto p = parent;
auto ch = &this;
while (p && ch is p.left)
{
ch = p;
p = p.parent;
}
return p;
}
/**
* Return the number of nodes in the subtree
**/
@property size_t size ()
{
auto c = 1;
if (left)
c += left.size;
if (right)
c += right.size;
return c;
}
/**
* Return node of current subtree containing value as value(),
* if it exists, else null.
* Uses Comparator cmp to find and to check equality.
**/
Ref find (V value, Compare!(V) cmp)
{
auto t = &this;
for (;;)
{
auto diff = cmp (value, t.value);
if (diff is 0)
return t;
else
if (diff < 0)
t = t.left;
else
t = t.right;
if (t is null)
break;
}
return null;
}
/**
* Return node of subtree matching "value"
* or, if none found, the one just after or before
* if it doesn't exist, return null
* Uses Comparator cmp to find and to check equality.
**/
Ref findFirst (V value, Compare!(V) cmp, bool after = true)
{
auto t = &this;
auto tLower = &this;
auto tGreater = &this;
for (;;)
{
auto diff = cmp (value, t.value);
if (diff is 0)
return t;
else
if (diff < 0)
{
tGreater = t;
t = t.left;
}
else
{
tLower = t;
t = t.right;
}
if (t is null)
break;
}
if (after)
{
if (cmp (value, tGreater.value) <= 0)
if (cmp (value, tGreater.value) < 0)
return tGreater;
}
else
{
if (cmp (value, tLower.value) >= 0)
if (cmp (value, tLower.value) > 0)
return tLower;
}
return null;
}
/**
* Return number of nodes of current subtree containing value.
* Uses Comparator cmp to find and to check equality.
**/
int count (V value, Compare!(V) cmp)
{
auto c = 0;
auto t = &this;
while (t)
{
int diff = cmp (value, t.value);
if (diff is 0)
{
++c;
if (t.left is null)
t = t.right;
else
if (t.right is null)
t = t.left;
else
{
c += t.right.count (value, cmp);
t = t.left;
}
}
else
if (diff < 0)
t = t.left;
else
t = t.right;
}
return c;
}
static if (!is(typeof(A) == AttributeDummy))
{
Ref findAttribute (A attribute, Compare!(A) cmp)
{
auto t = &this;
while (t)
{
if (t.attribute == attribute)
return t;
else
if (t.right is null)
t = t.left;
else
if (t.left is null)
t = t.right;
else
{
auto p = t.left.findAttribute (attribute, cmp);
if (p !is null)
return p;
else
t = t.right;
}
}
return null; // not reached
}
int countAttribute (A attrib, Compare!(A) cmp)
{
int c = 0;
auto t = &this;
while (t)
{
if (t.attribute == attribute)
++c;
if (t.right is null)
t = t.left;
else
if (t.left is null)
t = t.right;
else
{
c += t.left.countAttribute (attribute, cmp);
t = t.right;
}
}
return c;
}
/**
* find and return a cell holding (key, element), or null if no such
**/
Ref find (V value, A attribute, Compare!(V) cmp)
{
auto t = &this;
for (;;)
{
int diff = cmp (value, t.value);
if (diff is 0 && t.attribute == attribute)
return t;
else
if (diff <= 0)
t = t.left;
else
t = t.right;
if (t is null)
break;
}
return null;
}
}
/**
* Return a new subtree containing each value of current subtree
**/
Ref copyTree (scope Ref delegate() alloc)
{
auto t = dup (alloc);
if (left)
{
t.left = left.copyTree (alloc);
t.left.parent = t;
}
if (right)
{
t.right = right.copyTree (alloc);
t.right.parent = t;
}
return t;
}
/**
* There's no generic value insertion. Instead find the
* place you want to add a node and then invoke insertLeft
* or insertRight.
* <P>
* Insert Cell as the left child of current node, and then
* rebalance the tree it is in.
* @param Cell the Cell to add
* @param root, the root of the current tree
* Returns: the new root of the current tree. (Rebalancing
* can change the root!)
**/
Ref insertLeft (Ref cell, Ref root)
{
left = cell;
cell.parent = &this;
return cell.fixAfterInsertion (root);
}
/**
* Insert Cell as the right child of current node, and then
* rebalance the tree it is in.
* @param Cell the Cell to add
* @param root, the root of the current tree
* Returns: the new root of the current tree. (Rebalancing
* can change the root!)
**/
Ref insertRight (Ref cell, Ref root)
{
right = cell;
cell.parent = &this;
return cell.fixAfterInsertion (root);
}
/**
* Delete the current node, and then rebalance the tree it is in
* @param root the root of the current tree
* Returns: the new root of the current tree. (Rebalancing
* can change the root!)
**/
Ref remove (Ref root)
{
// handle case where we are only node
if (left is null && right is null && parent is null)
return null;
// if strictly internal, swap places with a successor
if (left && right)
{
auto s = successor;
// To work nicely with arbitrary subclasses of Ref, we don't want to
// just copy successor's fields. since we don't know what
// they are. Instead we swap positions _in the tree.
root = swapPosition (&this, s, root);
}
// Start fixup at replacement node (normally a child).
// But if no children, fake it by using self
if (left is null && right is null)
{
if (color is BLACK)
root = this.fixAfterDeletion (root);
// Unlink (Couldn't before since fixAfterDeletion needs parent ptr)
if (parent)
{
if (&this is parent.left)
parent.left = null;
else
if (&this is parent.right)
parent.right = null;
parent = null;
}
}
else
{
auto replacement = left;
if (replacement is null)
replacement = right;
// link replacement to parent
replacement.parent = parent;
if (parent is null)
root = replacement;
else
if (&this is parent.left)
parent.left = replacement;
else
parent.right = replacement;
left = null;
right = null;
parent = null;
// fix replacement
if (color is BLACK)
root = replacement.fixAfterDeletion (root);
}
return root;
}
/**
* Swap the linkages of two nodes in a tree.
* Return new root, in case it changed.
**/
static Ref swapPosition (Ref x, Ref y, Ref root)
{
/* Too messy. TODO: find sequence of assigments that are always OK */
auto px = x.parent;
bool xpl = px !is null && x is px.left;
auto lx = x.left;
auto rx = x.right;
auto py = y.parent;
bool ypl = py !is null && y is py.left;
auto ly = y.left;
auto ry = y.right;
if (x is py)
{
y.parent = px;
if (px !is null)
{
if (xpl)
px.left = y;
else
px.right = y;
}
x.parent = y;
if (ypl)
{
y.left = x;
y.right = rx;
if (rx !is null)
rx.parent = y;
}
else
{
y.right = x;
y.left = lx;
if (lx !is null)
lx.parent = y;
}
x.left = ly;
if (ly !is null)
ly.parent = x;
x.right = ry;
if (ry !is null)
ry.parent = x;
}
else
{
if (y is px)
{
x.parent = py;
if (py !is null)
{
if (ypl)
py.left = x;
else
py.right = x;
}
y.parent = x;
if (xpl)
{
x.left = y;
x.right = ry;
if (ry !is null)
ry.parent = x;
}
else
{
x.right = y;
x.left = ly;
if (ly !is null)
ly.parent = x;
}
y.left = lx;
if (lx !is null)
lx.parent = y;
y.right = rx;
if (rx !is null)
rx.parent = y;
}
else
{
x.parent = py;
if (py !is null)
{
if (ypl)
py.left = x;
else
py.right = x;
}
x.left = ly;
if (ly !is null)
ly.parent = x;
x.right = ry;
if (ry !is null)
ry.parent = x;
y.parent = px;
if (px !is null)
{
if (xpl)
px.left = y;
else
px.right = y;
}
y.left = lx;
if (lx !is null)
lx.parent = y;
y.right = rx;
if (rx !is null)
rx.parent = y;
}
}
bool c = x.color;
x.color = y.color;
y.color = c;
if (root is x)
root = y;
else
if (root is y)
root = x;
return root;
}
/**
* Return color of node p, or BLACK if p is null
* (In the CLR version, they use
* a special dummy `nil' node for such purposes, but that doesn't
* work well here, since it could lead to creating one such special
* node per real node.)
*
**/
static bool colorOf (Ref p)
{
return (p is null) ? BLACK : p.color;
}
/**
* return parent of node p, or null if p is null
**/
static Ref parentOf (Ref p)
{
return (p is null) ? null : p.parent;
}
/**
* Set the color of node p, or do nothing if p is null
**/
static void setColor (Ref p, bool c)
{
if (p !is null)
p.color = c;
}
/**
* return left child of node p, or null if p is null
**/
static Ref leftOf (Ref p)
{
return (p is null) ? null : p.left;
}
/**
* return right child of node p, or null if p is null
**/
static Ref rightOf (Ref p)
{
return (p is null) ? null : p.right;
}
/** From CLR **/
package Ref rotateLeft (Ref root)
{
auto r = right;
right = r.left;
if (r.left)
r.left.parent = &this;
r.parent = parent;
if (parent is null)
root = r;
else
if (parent.left is &this)
parent.left = r;
else
parent.right = r;
r.left = &this;
parent = r;
return root;
}
/** From CLR **/
package Ref rotateRight (Ref root)
{
auto l = left;
left = l.right;
if (l.right !is null)
l.right.parent = &this;
l.parent = parent;
if (parent is null)
root = l;
else
if (parent.right is &this)
parent.right = l;
else
parent.left = l;
l.right = &this;
parent = l;
return root;
}
/** From CLR **/
package Ref fixAfterInsertion (Ref root)
{
color = RED;
auto x = &this;
while (x && x !is root && x.parent.color is RED)
{
if (parentOf(x) is leftOf(parentOf(parentOf(x))))
{
auto y = rightOf(parentOf(parentOf(x)));
if (colorOf(y) is RED)
{
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
}
else
{
if (x is rightOf(parentOf(x)))
{
x = parentOf(x);
root = x.rotateLeft(root);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
if (parentOf(parentOf(x)) !is null)
root = parentOf(parentOf(x)).rotateRight(root);
}
}
else
{
auto y = leftOf(parentOf(parentOf(x)));
if (colorOf(y) is RED)
{
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
}
else
{
if (x is leftOf(parentOf(x)))
{
x = parentOf(x);
root = x.rotateRight(root);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
if (parentOf(parentOf(x)) !is null)
root = parentOf(parentOf(x)).rotateLeft(root);
}
}
}
root.color = BLACK;
return root;
}
/** From CLR **/
package Ref fixAfterDeletion(Ref root)
{
auto x = &this;
while (x !is root && colorOf(x) is BLACK)
{
if (x is leftOf(parentOf(x)))
{
auto sib = rightOf(parentOf(x));
if (colorOf(sib) is RED)
{
setColor(sib, BLACK);
setColor(parentOf(x), RED);
root = parentOf(x).rotateLeft(root);
sib = rightOf(parentOf(x));
}
if (colorOf(leftOf(sib)) is BLACK && colorOf(rightOf(sib)) is BLACK)
{
setColor(sib, RED);
x = parentOf(x);
}
else
{
if (colorOf(rightOf(sib)) is BLACK)
{
setColor(leftOf(sib), BLACK);
setColor(sib, RED);
root = sib.rotateRight(root);
sib = rightOf(parentOf(x));
}
setColor(sib, colorOf(parentOf(x)));
setColor(parentOf(x), BLACK);
setColor(rightOf(sib), BLACK);
root = parentOf(x).rotateLeft(root);
x = root;
}
}
else
{
auto sib = leftOf(parentOf(x));
if (colorOf(sib) is RED)
{
setColor(sib, BLACK);
setColor(parentOf(x), RED);
root = parentOf(x).rotateRight(root);
sib = leftOf(parentOf(x));
}
if (colorOf(rightOf(sib)) is BLACK && colorOf(leftOf(sib)) is BLACK)
{
setColor(sib, RED);
x = parentOf(x);
}
else
{
if (colorOf(leftOf(sib)) is BLACK)
{
setColor(rightOf(sib), BLACK);
setColor(sib, RED);
root = sib.rotateLeft(root);
sib = leftOf(parentOf(x));
}
setColor(sib, colorOf(parentOf(x)));
setColor(parentOf(x), BLACK);
setColor(leftOf(sib), BLACK);
root = parentOf(x).rotateRight(root);
x = root;
}
}
}
setColor(x, BLACK);
return root;
}
}
|