diff options
author | James Iry <jamesiry@gmail.com> | 2013-02-12 15:30:50 -0800 |
---|---|---|
committer | James Iry <jamesiry@gmail.com> | 2013-02-13 08:19:42 -0800 |
commit | 39037798c94e6e862f39dacffc5e65bb08b78d6a (patch) | |
tree | 57f5c17fa512ed1e07801f48d5c44ecd497617ea /src/library/scala/collection/immutable/RedBlackTree.scala | |
parent | 62bc99d3b20a7b37a977b19a6202cdac474eb5f6 (diff) | |
download | scala-39037798c94e6e862f39dacffc5e65bb08b78d6a.tar.gz scala-39037798c94e6e862f39dacffc5e65bb08b78d6a.tar.bz2 scala-39037798c94e6e862f39dacffc5e65bb08b78d6a.zip |
SI-6642 Refactor mutable.TreeSet to use RedBlackTree instead of AVL
There was no reason to have mutable.TreeSet use AVLTree while
immutable.TreeSet and immutable.HashSet used RedBlackTree. In
particular that would have meant duplicating the iteratorFrom logic
unnecessarily. So this commit refactors mutable.TreeSet to use
RedBlackTree for everything, including iteratorFrom. It also adds
a test to make sure TreeSet works as expected.
AVLTree should be dead code since it's private[scala.collection.mutable]
and only used by mutable.TreeSet, but to be safe it's only deprecated
in this commit.
Diffstat (limited to 'src/library/scala/collection/immutable/RedBlackTree.scala')
-rw-r--r-- | src/library/scala/collection/immutable/RedBlackTree.scala | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala index c0d46765be..d8c69f026b 100644 --- a/src/library/scala/collection/immutable/RedBlackTree.scala +++ b/src/library/scala/collection/immutable/RedBlackTree.scala @@ -24,7 +24,7 @@ import scala.annotation.meta.getter * * @since 2.10 */ -private[immutable] +private[collection] object RedBlackTree { def isEmpty(tree: Tree[_, _]): Boolean = tree eq null @@ -44,6 +44,25 @@ object RedBlackTree { } def count(tree: Tree[_, _]) = if (tree eq null) 0 else tree.count + /** + * Count all the nodes with keys greater than or equal to the lower bound and less than the upper bound. + * The two bounds are optional. + */ + def countInRange[A, _](tree: Tree[A, _], from: Option[A], to:Option[A])(implicit ordering: Ordering[A]) : Int = + if (tree eq null) 0 else + (from, to) match { + // with no bounds use this node's count + case (None, None) => tree.count + // if node is less than the lower bound, try the tree on the right, it might be in range + case (Some(lb), _) if ordering.lt(tree.key, lb) => countInRange(tree.right, from, to) + // if node is greater than or equal to the upper bound, try the tree on the left, it might be in range + case (_, Some(ub)) if ordering.gteq(tree.key, ub) => countInRange(tree.left, from, to) + // node is in range so the tree on the left will all be less than the upper bound and the tree on the + // right will all be greater than or equal to the lower bound. So 1 for this node plus + // count the subtrees by stripping off the bounds that we don't need any more + case _ => 1 + countInRange(tree.left, from, None) + countInRange(tree.right, None, to) + + } def update[A, B, B1 >: B](tree: Tree[A, B], k: A, v: B1, overwrite: Boolean)(implicit ordering: Ordering[A]): Tree[A, B1] = blacken(upd(tree, k, v, overwrite)) def delete[A, B](tree: Tree[A, B], k: A)(implicit ordering: Ordering[A]): Tree[A, B] = blacken(del(tree, k)) def rangeImpl[A: Ordering, B](tree: Tree[A, B], from: Option[A], until: Option[A]): Tree[A, B] = (from, until) match { |