summaryrefslogtreecommitdiff
path: root/src/library/scala/collection/immutable/RedBlackTree.scala
diff options
context:
space:
mode:
authorJames Iry <jamesiry@gmail.com>2013-02-12 15:30:50 -0800
committerJames Iry <jamesiry@gmail.com>2013-02-13 08:19:42 -0800
commit39037798c94e6e862f39dacffc5e65bb08b78d6a (patch)
tree57f5c17fa512ed1e07801f48d5c44ecd497617ea /src/library/scala/collection/immutable/RedBlackTree.scala
parent62bc99d3b20a7b37a977b19a6202cdac474eb5f6 (diff)
downloadscala-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.scala21
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 {