mirror of
https://github.com/dlang/phobos.git
synced 2025-05-08 20:19:43 +03:00
Merge branch 'jmdavis-red-black'
Conflicts: std/array.d
This commit is contained in:
commit
db5b27dcd2
3 changed files with 423 additions and 1665 deletions
1599
std/array.d
1599
std/array.d
File diff suppressed because it is too large
Load diff
469
std/container.d
469
std/container.d
|
@ -4105,13 +4105,10 @@ struct RBNode(V)
|
||||||
* ignored on insertion. If duplicates are allowed, then new elements are
|
* ignored on insertion. If duplicates are allowed, then new elements are
|
||||||
* inserted after all existing duplicate elements.
|
* inserted after all existing duplicate elements.
|
||||||
*/
|
*/
|
||||||
struct RedBlackTree(T, alias less = "a < b", bool allowDuplicates = false)
|
class RedBlackTree(T, alias less = "a < b", bool allowDuplicates = false)
|
||||||
if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
if(is(typeof(binaryFun!less(T.init, T.init))))
|
||||||
{
|
{
|
||||||
static if(is(typeof(less) == string))
|
alias binaryFun!less _less;
|
||||||
alias binaryFun!(less) _less;
|
|
||||||
else
|
|
||||||
alias less _less;
|
|
||||||
|
|
||||||
// BUG: this must come first in the struct due to issue 2810
|
// BUG: this must come first in the struct due to issue 2810
|
||||||
|
|
||||||
|
@ -4122,7 +4119,20 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
{
|
{
|
||||||
Node result;
|
Node result;
|
||||||
static if(!allowDuplicates)
|
static if(!allowDuplicates)
|
||||||
|
{
|
||||||
bool added = true;
|
bool added = true;
|
||||||
|
scope(success)
|
||||||
|
{
|
||||||
|
if(added)
|
||||||
|
++_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scope(success)
|
||||||
|
++_length;
|
||||||
|
}
|
||||||
|
|
||||||
if(!_end.left)
|
if(!_end.left)
|
||||||
{
|
{
|
||||||
_end.left = result = allocate(n);
|
_end.left = result = allocate(n);
|
||||||
|
@ -4204,11 +4214,6 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RedBlackTree create(Elem[] elems...)
|
|
||||||
{
|
|
||||||
return RedBlackTree(elems);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4224,9 +4229,11 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
private alias RBNode!Elem.Node Node;
|
private alias RBNode!Elem.Node Node;
|
||||||
|
|
||||||
private Node _end;
|
private Node _end;
|
||||||
|
private size_t _length;
|
||||||
|
|
||||||
private void _setup()
|
private void _setup()
|
||||||
{
|
{
|
||||||
|
assert(!_end); //Make sure that _setup isn't run more than once.
|
||||||
_end = allocate();
|
_end = allocate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4311,10 +4318,17 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
|
|
||||||
static if(doUnittest) unittest
|
static if(doUnittest) unittest
|
||||||
{
|
{
|
||||||
auto ts = create(1, 2, 3, 4, 5);
|
auto ts = new RedBlackTree(1, 2, 3, 4, 5);
|
||||||
|
assert(ts.length == 5);
|
||||||
auto r = ts[];
|
auto r = ts[];
|
||||||
assert(std.algorithm.equal(r, cast(T[])[1, 2, 3, 4, 5]));
|
|
||||||
assert(r.front == 1);
|
static if(less == "a < b")
|
||||||
|
auto vals = [1, 2, 3, 4, 5];
|
||||||
|
else
|
||||||
|
auto vals = [5, 4, 3, 2, 1];
|
||||||
|
|
||||||
|
assert(std.algorithm.equal(r, vals));
|
||||||
|
assert(r.front == vals.front);
|
||||||
assert(r.back != r.front);
|
assert(r.back != r.front);
|
||||||
auto oldfront = r.front;
|
auto oldfront = r.front;
|
||||||
auto oldback = r.back;
|
auto oldback = r.back;
|
||||||
|
@ -4323,6 +4337,7 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
assert(r.front != r.back);
|
assert(r.front != r.back);
|
||||||
assert(r.front != oldfront);
|
assert(r.front != oldfront);
|
||||||
assert(r.back != oldback);
|
assert(r.back != oldback);
|
||||||
|
assert(ts.length == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find a node based on an element value
|
// find a node based on an element value
|
||||||
|
@ -4372,27 +4387,37 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
return _end.left is null;
|
return _end.left is null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Returns the number of elements in the container.
|
||||||
|
|
||||||
|
Complexity: $(BIGOH 1).
|
||||||
|
+/
|
||||||
|
@property size_t length()
|
||||||
|
{
|
||||||
|
return _length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Duplicate this container. The resulting container contains a shallow
|
* Duplicate this container. The resulting container contains a shallow
|
||||||
* copy of the elements.
|
* copy of the elements.
|
||||||
*
|
*
|
||||||
* Complexity: $(BIGOH n)
|
* Complexity: $(BIGOH n)
|
||||||
*/
|
*/
|
||||||
RedBlackTree dup()
|
@property RedBlackTree dup()
|
||||||
{
|
{
|
||||||
RedBlackTree result;
|
return new RedBlackTree(_end.dup(), _length);
|
||||||
result._setup();
|
|
||||||
result._end = _end.dup();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static if(doUnittest) unittest
|
static if(doUnittest) unittest
|
||||||
{
|
{
|
||||||
auto ts = create(1, 2, 3, 4, 5);
|
auto ts = new RedBlackTree(1, 2, 3, 4, 5);
|
||||||
auto ts2 = ts.dup();
|
assert(ts.length == 5);
|
||||||
|
auto ts2 = ts.dup;
|
||||||
|
assert(ts2.length == 5);
|
||||||
assert(std.algorithm.equal(ts[], ts2[]));
|
assert(std.algorithm.equal(ts[], ts2[]));
|
||||||
ts2.insert(cast(Elem)6);
|
ts2.insert(cast(Elem)6);
|
||||||
assert(!std.algorithm.equal(ts[], ts2[]));
|
assert(!std.algorithm.equal(ts[], ts2[]));
|
||||||
|
assert(ts.length == 5 && ts2.length == 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4425,11 +4450,12 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
return _end.prev.value;
|
return _end.prev.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/++
|
||||||
* Check to see if an element exists in the container
|
$(D in) operator. Check to see if the given element exists in the
|
||||||
*
|
container.
|
||||||
* Complexity: $(BIGOH log(n))
|
|
||||||
*/
|
Complexity: $(BIGOH log(n))
|
||||||
|
+/
|
||||||
bool opBinaryRight(string op)(Elem e) if (op == "in")
|
bool opBinaryRight(string op)(Elem e) if (op == "in")
|
||||||
{
|
{
|
||||||
return _find(e) !is null;
|
return _find(e) !is null;
|
||||||
|
@ -4437,19 +4463,28 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
|
|
||||||
static if(doUnittest) unittest
|
static if(doUnittest) unittest
|
||||||
{
|
{
|
||||||
auto ts = create(1, 2, 3, 4, 5);
|
auto ts = new RedBlackTree(1, 2, 3, 4, 5);
|
||||||
assert(cast(Elem)3 in ts);
|
assert(cast(Elem)3 in ts);
|
||||||
assert(cast(Elem)6 !in ts);
|
assert(cast(Elem)6 !in ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the container of all elements
|
* Removes all elements from the container.
|
||||||
*
|
*
|
||||||
* Complexity: $(BIGOH 1)
|
* Complexity: $(BIGOH 1)
|
||||||
*/
|
*/
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
_end.left = null;
|
_end.left = null;
|
||||||
|
_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static if(doUnittest) unittest
|
||||||
|
{
|
||||||
|
auto ts = new RedBlackTree(1,2,3,4,5);
|
||||||
|
assert(ts.length == 5);
|
||||||
|
ts.clear();
|
||||||
|
assert(ts.empty && ts.length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4504,10 +4539,33 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
|
|
||||||
static if(doUnittest) unittest
|
static if(doUnittest) unittest
|
||||||
{
|
{
|
||||||
auto ts = create(1,2,3,4,5);
|
auto ts = new RedBlackTree(2,1,3,4,5,2,5);
|
||||||
assert(ts.stableInsert(cast(Elem[])[6, 7, 8, 9, 10]) == 5);
|
static if(allowDuplicates)
|
||||||
assert(ts.stableInsert(cast(Elem)11) == 1);
|
{
|
||||||
|
assert(ts.length == 7);
|
||||||
|
assert(ts.stableInsert(cast(Elem[])[7, 8, 6, 9, 10, 8]) == 6);
|
||||||
|
assert(ts.length == 13);
|
||||||
|
assert(ts.stableInsert(cast(Elem)11) == 1 && ts.length == 14);
|
||||||
|
assert(ts.stableInsert(cast(Elem)7) == 1 && ts.length == 15);
|
||||||
|
|
||||||
|
static if(less == "a < b")
|
||||||
|
assert(ts.arrayEqual([1,2,2,3,4,5,5,6,7,7,8,8,9,10,11]));
|
||||||
|
else
|
||||||
|
assert(ts.arrayEqual([11,10,9,8,8,7,7,6,5,5,4,3,2,2,1]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(ts.length == 5);
|
||||||
|
assert(ts.stableInsert(cast(Elem[])[7, 8, 6, 9, 10, 8]) == 5);
|
||||||
|
assert(ts.length == 10);
|
||||||
|
assert(ts.stableInsert(cast(Elem)11) == 1 && ts.length == 11);
|
||||||
|
assert(ts.stableInsert(cast(Elem)7) == 0 && ts.length == 11);
|
||||||
|
|
||||||
|
static if(less == "a < b")
|
||||||
assert(ts.arrayEqual([1,2,3,4,5,6,7,8,9,10,11]));
|
assert(ts.arrayEqual([1,2,3,4,5,6,7,8,9,10,11]));
|
||||||
|
else
|
||||||
|
assert(ts.arrayEqual([11,10,9,8,7,6,5,4,3,2,1]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4517,6 +4575,8 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
*/
|
*/
|
||||||
Elem removeAny()
|
Elem removeAny()
|
||||||
{
|
{
|
||||||
|
scope(success)
|
||||||
|
--_length;
|
||||||
auto n = _end.leftmost;
|
auto n = _end.leftmost;
|
||||||
auto result = n.value;
|
auto result = n.value;
|
||||||
n.remove(_end);
|
n.remove(_end);
|
||||||
|
@ -4527,8 +4587,10 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
|
|
||||||
static if(doUnittest) unittest
|
static if(doUnittest) unittest
|
||||||
{
|
{
|
||||||
auto ts = create(1,2,3,4,5);
|
auto ts = new RedBlackTree(1,2,3,4,5);
|
||||||
|
assert(ts.length == 5);
|
||||||
auto x = ts.removeAny();
|
auto x = ts.removeAny();
|
||||||
|
assert(ts.length == 4);
|
||||||
Elem[] arr;
|
Elem[] arr;
|
||||||
foreach(Elem i; 1..6)
|
foreach(Elem i; 1..6)
|
||||||
if(i != x) arr ~= i;
|
if(i != x) arr ~= i;
|
||||||
|
@ -4542,6 +4604,8 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
*/
|
*/
|
||||||
void removeFront()
|
void removeFront()
|
||||||
{
|
{
|
||||||
|
scope(success)
|
||||||
|
--_length;
|
||||||
_end.leftmost.remove(_end);
|
_end.leftmost.remove(_end);
|
||||||
version(RBDoChecks)
|
version(RBDoChecks)
|
||||||
check();
|
check();
|
||||||
|
@ -4554,6 +4618,8 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
*/
|
*/
|
||||||
void removeBack()
|
void removeBack()
|
||||||
{
|
{
|
||||||
|
scope(success)
|
||||||
|
--_length;
|
||||||
_end.prev.remove(_end);
|
_end.prev.remove(_end);
|
||||||
version(RBDoChecks)
|
version(RBDoChecks)
|
||||||
check();
|
check();
|
||||||
|
@ -4561,19 +4627,29 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
|
|
||||||
static if(doUnittest) unittest
|
static if(doUnittest) unittest
|
||||||
{
|
{
|
||||||
auto ts = create(1,2,3,4,5);
|
auto ts = new RedBlackTree(1,2,3,4,5);
|
||||||
|
assert(ts.length == 5);
|
||||||
ts.removeBack();
|
ts.removeBack();
|
||||||
|
assert(ts.length == 4);
|
||||||
|
|
||||||
|
static if(less == "a < b")
|
||||||
assert(ts.arrayEqual([1,2,3,4]));
|
assert(ts.arrayEqual([1,2,3,4]));
|
||||||
|
else
|
||||||
|
assert(ts.arrayEqual([2,3,4,5]));
|
||||||
|
|
||||||
ts.removeFront();
|
ts.removeFront();
|
||||||
assert(ts.arrayEqual([2,3,4]));
|
assert(ts.arrayEqual([2,3,4]) && ts.length == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/++
|
||||||
* Remove the given range from the container. Returns a range containing
|
Removes the given range from the container.
|
||||||
* all the elements that were after the given range.
|
|
||||||
*
|
Returns: A range containing all of the elements that were after the
|
||||||
* Complexity: $(BIGOH m * log(n))
|
given range.
|
||||||
*/
|
|
||||||
|
Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
|
||||||
|
the range)
|
||||||
|
+/
|
||||||
Range remove(Range r)
|
Range remove(Range r)
|
||||||
{
|
{
|
||||||
auto b = r._begin;
|
auto b = r._begin;
|
||||||
|
@ -4581,6 +4657,7 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
while(b !is e)
|
while(b !is e)
|
||||||
{
|
{
|
||||||
b = b.remove(_end);
|
b = b.remove(_end);
|
||||||
|
--_length;
|
||||||
}
|
}
|
||||||
version(RBDoChecks)
|
version(RBDoChecks)
|
||||||
check();
|
check();
|
||||||
|
@ -4589,13 +4666,159 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
|
|
||||||
static if(doUnittest) unittest
|
static if(doUnittest) unittest
|
||||||
{
|
{
|
||||||
auto ts = create(1,2,3,4,5);
|
auto ts = new RedBlackTree(1,2,3,4,5);
|
||||||
|
assert(ts.length == 5);
|
||||||
auto r = ts[];
|
auto r = ts[];
|
||||||
r.popFront();
|
r.popFront();
|
||||||
r.popBack();
|
r.popBack();
|
||||||
|
assert(ts.length == 5);
|
||||||
auto r2 = ts.remove(r);
|
auto r2 = ts.remove(r);
|
||||||
|
assert(ts.length == 2);
|
||||||
assert(ts.arrayEqual([1,5]));
|
assert(ts.arrayEqual([1,5]));
|
||||||
|
|
||||||
|
static if(less == "a < b")
|
||||||
assert(std.algorithm.equal(r2, [5]));
|
assert(std.algorithm.equal(r2, [5]));
|
||||||
|
else
|
||||||
|
assert(std.algorithm.equal(r2, [1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Removes the given $(D Take!Range) from the container
|
||||||
|
|
||||||
|
Returns: A range containing all of the elements that were after the
|
||||||
|
given range.
|
||||||
|
|
||||||
|
Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
|
||||||
|
the range)
|
||||||
|
+/
|
||||||
|
Range remove(Take!Range r)
|
||||||
|
{
|
||||||
|
auto b = r.original._begin;
|
||||||
|
|
||||||
|
while(!r.empty)
|
||||||
|
r.popFront(); // move take range to its last element
|
||||||
|
|
||||||
|
auto e = r.original._begin;
|
||||||
|
|
||||||
|
while(b != e)
|
||||||
|
{
|
||||||
|
b = b.remove(_end);
|
||||||
|
--_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Range(e, _end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static if(doUnittest) unittest
|
||||||
|
{
|
||||||
|
auto ts = new RedBlackTree(1,2,3,4,5);
|
||||||
|
auto r = ts[];
|
||||||
|
r.popFront();
|
||||||
|
assert(ts.length == 5);
|
||||||
|
auto r2 = ts.remove(take(r, 0));
|
||||||
|
|
||||||
|
static if(less == "a < b")
|
||||||
|
{
|
||||||
|
assert(std.algorithm.equal(r2, [2,3,4,5]));
|
||||||
|
auto r3 = ts.remove(take(r, 2));
|
||||||
|
assert(ts.arrayEqual([1,4,5]) && ts.length == 3);
|
||||||
|
assert(std.algorithm.equal(r3, [4,5]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(std.algorithm.equal(r2, [4,3,2,1]));
|
||||||
|
auto r3 = ts.remove(take(r, 2));
|
||||||
|
assert(ts.arrayEqual([5,2,1]) && ts.length == 3);
|
||||||
|
assert(std.algorithm.equal(r3, [2,1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Removes elements from the container that are equal to the given values
|
||||||
|
according to the less comparator. One element is removed for each value
|
||||||
|
given which is in the container. If $(D allowDuplicates) is true,
|
||||||
|
duplicates are removed only if duplicate values are given.
|
||||||
|
|
||||||
|
Returns: The number of elements removed.
|
||||||
|
|
||||||
|
Complexity: $(BIGOH m log(n)) (where m is the number of elements to remove)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
--------------------
|
||||||
|
auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
|
||||||
|
rbt.removeKey(1, 4, 7);
|
||||||
|
assert(std.algorithm.equal(rbt[], [0, 1, 1, 5]));
|
||||||
|
rbt.removeKey(1, 1, 0);
|
||||||
|
assert(std.algorithm.equal(rbt[], [5]));
|
||||||
|
--------------------
|
||||||
|
+/
|
||||||
|
size_t removeKey(U)(U[] elems...)
|
||||||
|
if(isImplicitlyConvertible!(U, Elem))
|
||||||
|
{
|
||||||
|
immutable lenBefore = length;
|
||||||
|
|
||||||
|
foreach(e; elems)
|
||||||
|
{
|
||||||
|
auto beg = _firstGreaterEqual(e);
|
||||||
|
if(beg is _end || _less(e, beg.value))
|
||||||
|
// no values are equal
|
||||||
|
continue;
|
||||||
|
beg.remove(_end);
|
||||||
|
--_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lenBefore - length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/++ Ditto +/
|
||||||
|
size_t removeKey(Stuff)(Stuff stuff)
|
||||||
|
if(isInputRange!Stuff &&
|
||||||
|
isImplicitlyConvertible!(ElementType!Stuff, Elem) &&
|
||||||
|
!is(Stuff == Elem[]))
|
||||||
|
{
|
||||||
|
//We use array in case stuff is a Range from this RedBlackTree - either
|
||||||
|
//directly or indirectly.
|
||||||
|
return removeKey(array(stuff));
|
||||||
|
}
|
||||||
|
|
||||||
|
static if(doUnittest) unittest
|
||||||
|
{
|
||||||
|
auto rbt = new RedBlackTree(5, 4, 3, 7, 2, 1, 7, 6, 2, 19, 45);
|
||||||
|
|
||||||
|
static if(allowDuplicates)
|
||||||
|
{
|
||||||
|
assert(rbt.length == 11);
|
||||||
|
assert(rbt.removeKey(cast(Elem)4) == 1 && rbt.length == 10);
|
||||||
|
assert(rbt.arrayEqual([1,2,2,3,5,6,7,7,19,45]) && rbt.length == 10);
|
||||||
|
|
||||||
|
assert(rbt.removeKey(cast(Elem)6, cast(Elem)2, cast(Elem)1) == 3);
|
||||||
|
assert(rbt.arrayEqual([2,3,5,7,7,19,45]) && rbt.length == 7);
|
||||||
|
|
||||||
|
assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 7);
|
||||||
|
assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 4);
|
||||||
|
|
||||||
|
static if(less == "a < b")
|
||||||
|
assert(std.algorithm.equal(rbt[], [7,7,19,45]));
|
||||||
|
else
|
||||||
|
assert(std.algorithm.equal(rbt[], [7,5,3,2]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(rbt.length == 9);
|
||||||
|
assert(rbt.removeKey(cast(Elem)4) == 1 && rbt.length == 8);
|
||||||
|
assert(rbt.arrayEqual([1,2,3,5,6,7,19,45]));
|
||||||
|
|
||||||
|
assert(rbt.removeKey(cast(Elem)6, cast(Elem)2, cast(Elem)1) == 3);
|
||||||
|
assert(rbt.arrayEqual([3,5,7,19,45]) && rbt.length == 5);
|
||||||
|
|
||||||
|
assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 5);
|
||||||
|
assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 2);
|
||||||
|
|
||||||
|
static if(less == "a < b")
|
||||||
|
assert(std.algorithm.equal(rbt[], [19,45]));
|
||||||
|
else
|
||||||
|
assert(std.algorithm.equal(rbt[], [5,3]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the first node where the value is > e
|
// find the first node where the value is > e
|
||||||
|
@ -4685,18 +4908,28 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
|
|
||||||
static if(doUnittest) unittest
|
static if(doUnittest) unittest
|
||||||
{
|
{
|
||||||
auto ts = create(1, 2, 3, 4, 5);
|
auto ts = new RedBlackTree(1, 2, 3, 4, 5);
|
||||||
auto r1 = ts.lowerBound(3);
|
auto rl = ts.lowerBound(3);
|
||||||
assert(std.algorithm.equal(r1, [1,2]));
|
auto ru = ts.upperBound(3);
|
||||||
auto r2 = ts.upperBound(3);
|
auto re = ts.equalRange(3);
|
||||||
assert(std.algorithm.equal(r2, [4,5]));
|
|
||||||
auto r3 = ts.equalRange(3);
|
static if(less == "a < b")
|
||||||
assert(std.algorithm.equal(r3, [3]));
|
{
|
||||||
|
assert(std.algorithm.equal(rl, [1,2]));
|
||||||
|
assert(std.algorithm.equal(ru, [4,5]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(std.algorithm.equal(rl, [5,4]));
|
||||||
|
assert(std.algorithm.equal(ru, [2,1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(std.algorithm.equal(re, [3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
version(RBDoChecks)
|
version(RBDoChecks)
|
||||||
{
|
{
|
||||||
/**
|
/*
|
||||||
* Print the tree. This prints a sideways view of the tree in ASCII form,
|
* Print the tree. This prints a sideways view of the tree in ASCII form,
|
||||||
* with the number of indentations representing the level of the nodes.
|
* with the number of indentations representing the level of the nodes.
|
||||||
* It does not print values, only the tree structure and color of nodes.
|
* It does not print values, only the tree structure and color of nodes.
|
||||||
|
@ -4721,7 +4954,7 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
writeln();
|
writeln();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Check the tree for validity. This is called after every add or remove.
|
* Check the tree for validity. This is called after every add or remove.
|
||||||
* This should only be enabled to debug the implementation of the RB Tree.
|
* This should only be enabled to debug the implementation of the RB Tree.
|
||||||
*/
|
*/
|
||||||
|
@ -4777,6 +5010,11 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/+
|
||||||
|
For the moment, using templatized contstructors doesn't seem to work
|
||||||
|
very well (likely due to bug# 436 and/or bug# 1528). The redBlackTree
|
||||||
|
helper function seems to do the job well enough though.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Pass in an array of elements, or individual elements to
|
* Constructor. Pass in an array of elements, or individual elements to
|
||||||
* initialize the tree with.
|
* initialize the tree with.
|
||||||
|
@ -4795,17 +5033,136 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
|
||||||
_setup();
|
_setup();
|
||||||
stableInsert(stuff);
|
stableInsert(stuff);
|
||||||
}
|
}
|
||||||
|
+/
|
||||||
|
|
||||||
|
/++ +/
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
_setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Constructor. Pass in an array of elements, or individual elements to
|
||||||
|
initialize the tree with.
|
||||||
|
+/
|
||||||
|
this(Elem[] elems...)
|
||||||
|
{
|
||||||
|
_setup();
|
||||||
|
stableInsert(elems);
|
||||||
|
}
|
||||||
|
|
||||||
|
private this(Node end, size_t length)
|
||||||
|
{
|
||||||
|
_end = end;
|
||||||
|
_length = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Verify Example for removeKey.
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
|
||||||
|
rbt.removeKey(1, 4, 7);
|
||||||
|
assert(std.algorithm.equal(rbt[], [0, 1, 1, 5]));
|
||||||
|
rbt.removeKey(1, 1, 0);
|
||||||
|
assert(std.algorithm.equal(rbt[], [5]));
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
RedBlackTree!uint rt1;
|
void test(T)()
|
||||||
RedBlackTree!int rt2;
|
{
|
||||||
RedBlackTree!ushort rt3;
|
auto rt1 = new RedBlackTree!(T, "a < b", false)();
|
||||||
RedBlackTree!short rt4;
|
auto rt2 = new RedBlackTree!(T, "a < b", true)();
|
||||||
RedBlackTree!ubyte rt5;
|
auto rt3 = new RedBlackTree!(T, "a > b", false)();
|
||||||
RedBlackTree!byte rt6;
|
auto rt4 = new RedBlackTree!(T, "a > b", true)();
|
||||||
|
}
|
||||||
|
|
||||||
|
test!long();
|
||||||
|
test!ulong();
|
||||||
|
test!int();
|
||||||
|
test!uint();
|
||||||
|
test!short();
|
||||||
|
test!ushort();
|
||||||
|
test!byte();
|
||||||
|
test!byte();
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Convenience function for creating a $(D RedBlackTree!E) from a list of
|
||||||
|
values.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
--------------------
|
||||||
|
auto rbt1 = redBlackTree(0, 1, 5, 7);
|
||||||
|
auto rbt2 = redBlackTree!string("hello", "world");
|
||||||
|
auto rbt3 = redBlackTree!true(0, 1, 5, 7, 5);
|
||||||
|
auto rbt4 = redBlackTree!"a > b"(0, 1, 5, 7);
|
||||||
|
auto rbt5 = redBlackTree!("a > b", true)(0.1, 1.3, 5.9, 7.2, 5.9);
|
||||||
|
--------------------
|
||||||
|
+/
|
||||||
|
auto redBlackTree(E)(E[] elems...)
|
||||||
|
{
|
||||||
|
return new RedBlackTree!E(elems);
|
||||||
|
}
|
||||||
|
|
||||||
|
/++ Ditto +/
|
||||||
|
auto redBlackTree(bool allowDuplicates, E)(E[] elems...)
|
||||||
|
{
|
||||||
|
return new RedBlackTree!(E, "a < b", allowDuplicates)(elems);
|
||||||
|
}
|
||||||
|
|
||||||
|
/++ Ditto +/
|
||||||
|
auto redBlackTree(alias less, E)(E[] elems...)
|
||||||
|
{
|
||||||
|
return new RedBlackTree!(E, less)(elems);
|
||||||
|
}
|
||||||
|
|
||||||
|
/++ Ditto +/
|
||||||
|
auto redBlackTree(alias less, bool allowDuplicates, E)(E[] elems...)
|
||||||
|
if(is(typeof(binaryFun!less(E.init, E.init))))
|
||||||
|
{
|
||||||
|
//We shouldn't need to instantiate less here, but for some reason,
|
||||||
|
//dmd can't handle it if we don't (even though the template which
|
||||||
|
//takes less but not allowDuplicates works just fine).
|
||||||
|
return new RedBlackTree!(E, binaryFun!less, allowDuplicates)(elems);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Verify Examples.
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
auto rbt1 = redBlackTree(0, 1, 5, 7);
|
||||||
|
auto rbt2 = redBlackTree!string("hello", "world");
|
||||||
|
auto rbt3 = redBlackTree!true(0, 1, 5, 7, 5);
|
||||||
|
auto rbt4 = redBlackTree!"a > b"(0, 1, 5, 7);
|
||||||
|
auto rbt5 = redBlackTree!("a > b", true)(0.1, 1.3, 5.9, 7.2, 5.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Combinations not in examples.
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
auto rbt1 = redBlackTree!(true, string)("hello", "hello");
|
||||||
|
auto rbt2 = redBlackTree!((a, b){return a < b;}, double)(5.1, 2.3);
|
||||||
|
auto rbt3 = redBlackTree!("a > b", true, string)("hello", "world");
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
auto rt1 = redBlackTree(5, 4, 3, 2, 1);
|
||||||
|
assert(rt1.length == 5);
|
||||||
|
assert(array(rt1[]) == [1, 2, 3, 4, 5]);
|
||||||
|
|
||||||
|
auto rt2 = redBlackTree!"a > b"(1.1, 2.1);
|
||||||
|
assert(rt2.length == 2);
|
||||||
|
assert(array(rt2[]) == [2.1, 1.1]);
|
||||||
|
|
||||||
|
auto rt3 = redBlackTree!true(5, 5, 4);
|
||||||
|
assert(rt3.length == 3);
|
||||||
|
assert(array(rt3[]) == [4, 5, 5]);
|
||||||
|
|
||||||
|
auto rt4 = redBlackTree!string("hello", "hello");
|
||||||
|
assert(rt4.length == 1);
|
||||||
|
assert(array(rt4[]) == ["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
version(unittest) struct UnittestMe {
|
version(unittest) struct UnittestMe {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue