Scala::树映射在更新后不平衡?
我想做的是能够调整TreeMap中项目的键顺序,所以 我可能可以通过一些静态数据找到一个对象,这些数据不会改变 如果贴图是展平的,则对象的位置应考虑其优先级 以下测试用例适用于numEntries=6,但不适用于大于7的值。我真的不明白那里出了什么问题,但我怀疑在一些更新/拷贝之后,树会被解除。所以,有人可以提出建议吗?是我的错还是Scala 2.9中的树形图有某种缺陷 如果循环失败,则更新Scala::树映射在更新后不平衡?,scala,immutability,treemap,Scala,Immutability,Treemap,我想做的是能够调整TreeMap中项目的键顺序,所以 我可能可以通过一些静态数据找到一个对象,这些数据不会改变 如果贴图是展平的,则对象的位置应考虑其优先级 以下测试用例适用于numEntries=6,但不适用于大于7的值。我真的不明白那里出了什么问题,但我怀疑在一些更新/拷贝之后,树会被解除。所以,有人可以提出建议吗?是我的错还是Scala 2.9中的树形图有某种缺陷 如果循环失败,则更新 for (i <- 1 to (numEntries - 1)) { 替换为 for (i &l
for (i <- 1 to (numEntries - 1)) {
替换为
for (i <- (numEntries - 1) to 1 by -1) {
一切正常。看来这就是树状图中的错误
import org.scalatest.FlatSpec
import collection.immutable.TreeMap
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
@RunWith(classOf[JUnitRunner])
class TreeMapTest extends FlatSpec {
//val numEntries = 6;
val numEntries = 10;
sealed case class Entry(first: Option[Int], last: Int) extends Ordered[Entry] {
def compare(that: TreeMapTest.this.type#Entry) = {
if (first.isEmpty || that.first.isEmpty) {
last compare that.last
} else {
(first.get compare that.first.get) match {
case 0 => last compare that.last
case x => x
}
}
}
def increase() = copy(first = Some(this.first.getOrElse(0) + 1))
}
type Container = TreeMap[Entry, Entry]
"TreeMap" should "allow updates" in {
var dataMap: Container = new Container() ++ (for (i <- 1 to numEntries) yield Entry(Some(0), i) -> Entry(Some(0), i))
for (i <- 1 to (numEntries - 1)) {
val key = new Entry(None, i)
dataMap.get(new Entry(None, i)) match {
case Some(e) =>
val newEntry = e.increase()
dataMap = (dataMap - key) + (newEntry -> newEntry)
case None => fail("Can not find entry " + key)
}
}
}
}
我发现TreeMap基本操作中不太可能有bug——Scala 2.9.0之前有很多bug,但现在有一个强大的测试套件支持RedBlack,它支持store 更有可能的是,问题出现在您没有一个完整的订单。假设你有三个要素:
val a = Entry(Some(0), 3)
val b = Entry(Some(1), 0)
val c = Entry(None, 1)
那么以下是正确的:
scala> a < b
res39: Boolean = true
scala> b < c
res40: Boolean = true
scala> c < a
res41: Boolean = true
因此,d
b
/ \
a e
/
d
现在,如果你在这棵树中查找c,你会首先比较c和b,发现c比b大。这意味着您将只查看包含e的正确分支,而永远不会找到d。我发现TreeMap基本操作中不太可能有错误-Scala 2.9.0之前有很多错误,但现在有一个强大的测试套件支持RedBlack,它支持store 更有可能的是,问题出现在您没有一个完整的订单。假设你有三个要素:
val a = Entry(Some(0), 3)
val b = Entry(Some(1), 0)
val c = Entry(None, 1)
那么以下是正确的:
scala> a < b
res39: Boolean = true
scala> b < c
res40: Boolean = true
scala> c < a
res41: Boolean = true
因此,d
b
/ \
a e
/
d
现在,如果你在这棵树中查找c,你会首先比较c和b,发现c比b大。这意味着您将只查看包含e的右侧分支,您将永远不会找到d。首选1直到numEntries超过1到numEntries-1。首选1直到numEntries超过1到numEntries-1。那么,如果我以相反的顺序迭代,它为什么能正常工作呢?另外请注意,我没有在地图中没有的项目,它只在我知道有效负载的情况下使用,但不知道项目的当前顺序。因此,当我在地图中插入一些东西时,它定义了严格且一致的顺序。这纯粹是运气,算法在后退时选择了正确的比较。正如Daniel指出的,您的比较函数被破坏了,但这并不意味着它在幸运的情况下不能产生正确的结果。@jdevelop我举了一个有效树的例子来重现您的问题。那么,如果我按相反的顺序迭代,为什么它能正常工作呢?另外请注意,我没有在地图中没有的项目,它只在我知道有效负载的情况下使用,但不知道项目的当前顺序。因此,当我在地图中插入一些东西时,它定义了严格且一致的顺序。这纯粹是运气,算法在后退时选择了正确的比较。正如Daniel指出的,您的比较函数被破坏了,但这并不意味着它在幸运的情况下不能产生正确的结果。@jdevelop我举了一个有效树的例子来重现您的问题。