@@ -26,6 +26,21 @@ import scala.runtime.Statics.releaseFence
26
26
* optimizations behind a reasonably clean API.
27
27
*/
28
28
private [collection] object RedBlackTree {
29
+ def validate [A ](tree : Tree [A , _])(implicit ordering : Ordering [A ]): tree.type = {
30
+ def impl (tree : Tree [A , _], keyProp : A => Boolean ): Int = {
31
+ assert(keyProp(tree.key), s " key check failed: $tree" )
32
+ if (tree.isRed) {
33
+ assert(tree.left == null || tree.left.isBlack, s " red-red left $tree" )
34
+ assert(tree.right == null || tree.right.isBlack, s " red-red right $tree" )
35
+ }
36
+ val leftBlacks = if (tree.left == null ) 0 else impl(tree.left, k => keyProp(k) && ordering.compare(k, tree.key) < 0 )
37
+ val rightBlacks = if (tree.right == null ) 0 else impl(tree.right, k => keyProp(k) && ordering.compare(k, tree.key) > 0 )
38
+ assert(leftBlacks == rightBlacks, s " not balanced: $tree" )
39
+ leftBlacks + (if (tree.isBlack) 1 else 0 )
40
+ }
41
+ if (tree != null ) impl(tree, _ => true )
42
+ tree
43
+ }
29
44
30
45
def isEmpty (tree : Tree [_, _]): Boolean = tree eq null
31
46
@@ -437,23 +452,23 @@ private[collection] object RedBlackTree {
437
452
if (ordering.lt(tree.key, from)) return doFrom(tree.right, from)
438
453
val newLeft = doFrom(tree.left, from)
439
454
if (newLeft eq tree.left) tree
440
- else if (newLeft eq null ) upd(tree.right, tree.key, tree.value, overwrite = false )
455
+ else if (newLeft eq null ) maybeBlacken( upd(tree.right, tree.key, tree.value, overwrite = false ) )
441
456
else join(newLeft, tree.key, tree.value, tree.right)
442
457
}
443
458
private [this ] def doTo [A , B ](tree : Tree [A , B ], to : A )(implicit ordering : Ordering [A ]): Tree [A , B ] = {
444
459
if (tree eq null ) return null
445
460
if (ordering.lt(to, tree.key)) return doTo(tree.left, to)
446
461
val newRight = doTo(tree.right, to)
447
462
if (newRight eq tree.right) tree
448
- else if (newRight eq null ) upd(tree.left, tree.key, tree.value, overwrite = false )
449
- else join (tree.left, tree.key, tree.value, newRight)
463
+ else if (newRight eq null ) maybeBlacken( upd(tree.left, tree.key, tree.value, overwrite = false ) )
464
+ else join(tree.left, tree.key, tree.value, newRight)
450
465
}
451
466
private [this ] def doUntil [A , B ](tree : Tree [A , B ], until : A )(implicit ordering : Ordering [A ]): Tree [A , B ] = {
452
467
if (tree eq null ) return null
453
468
if (ordering.lteq(until, tree.key)) return doUntil(tree.left, until)
454
469
val newRight = doUntil(tree.right, until)
455
470
if (newRight eq tree.right) tree
456
- else if (newRight eq null ) upd(tree.left, tree.key, tree.value, overwrite = false )
471
+ else if (newRight eq null ) maybeBlacken( upd(tree.left, tree.key, tree.value, overwrite = false ) )
457
472
else join(tree.left, tree.key, tree.value, newRight)
458
473
}
459
474
0 commit comments