在Scala中实现二叉树

在Scala中实现二叉树,scala,Scala,我在Scala中设置二叉树时遇到困难。它的类型参数必须是协变的(以允许空树类型),其键的类型必须是Ordered的子类,以允许与其他键进行比较。这就是我到目前为止所做的: package tutorial class AbTree[+K <: Ordered[K],+V] { def throwTreeException(msg:String) = throw new Exception("TreeException: " + msg) def

我在Scala中设置二叉树时遇到困难。它的类型参数必须是协变的(以允许空树类型),其键的类型必须是Ordered的子类,以允许与其他键进行比较。这就是我到目前为止所做的:

package tutorial

class AbTree[+K <: Ordered[K],+V] {
    def throwTreeException(msg:String) = throw new
            Exception("TreeException: " + msg)

    def replaceL[L >: K, W >: V](nTree:AbTree[L,W]): AbTree[L,W] = this match {
        case ETree => throwTreeException("replaceL called on an ETree")
        case tree:Tree[L,W] => tree.copy(lTree = nTree)
    }

    def replaceR[L >: K, W >: V](nTree:AbTree[L,W]): AbTree[L,W] = this match {
        case ETree          => throwTreeException("replaceR called on an ETree")
        case tree:Tree[L,W] => tree.copy(rTree = nTree)
    }

    def insert[L >: K, W >: V](nK:L,nV:W): AbTree[L,W] = this match {
        case ETree => Tree(nK,nV)                                           //Line 18
        case Tree(k,v,lT,rT) =>
            if (nK < k) replaceL(lT.insert(nK,nV))
            else if (nK > k) replaceR(rT.insert(nK,nV))                     //Line 21
            else Tree(k,v,lT,rT)
    }
}

case class Tree[+K <: Ordered[K],+V]
    (key:K,value:V,lTree:AbTree[K,V] = ETree,rTree:AbTree[K,V] = ETree)
    extends AbTree[K,V]

case object ETree
    extends AbTree[Nothing,Nothing]
这只是我尝试的类型边界的一种组合。我在这个过程中犯了很多错误,我不知道哪些是真正的问题,哪些是由其他问题引起的;所以我不知道从哪里开始


我猜我的理解在某个地方有一个巨大的漏洞。有人能指出我上面提到的主要问题是什么吗?

以此作为灵感。请看一下在Scala中映射的实现。键类型不是协变的,值类型是。也许定义
isEmpty
方法比模式匹配对象更有意义

class AbTree[K, +V](implicit ordering: Ordering[K]) {
  def throwTreeException(msg:String) = throw new
      Exception("TreeException: " + msg)

  def replaceL[W >: V](nTree:AbTree[K, W]): AbTree[K, W] = {
    val empty = AbTree.empty[K, V]
    this match {
      case `empty` => throwTreeException("replaceL called on an ETree")
      case tree:Tree[K, W] => tree.copy(lTree = nTree)
    }
  }

  def replaceR[W >: V](nTree:AbTree[K, W]): AbTree[K, W] = {
    val empty = AbTree.empty[K, V]
    this match {
      case `empty`          => throwTreeException("replaceR called on an ETree")
      case tree:Tree[K, W] => tree.copy(rTree = nTree)
    }
  }

  def insert[W >: V](nK:K,nV:W): AbTree[K,W] = {
    val empty = AbTree.empty[K, V]
    this match {
      case `empty` => Tree(nK, nV) //Line 18
      case Tree(k, v, lT, rT) =>
        if (ordering.compare(nK, k) < 0) replaceL(lT.insert(nK, nV))
        else if (ordering.compare(nK, k) > 0) replaceR(rT.insert(nK, nV)) //Line 21
        else Tree(k, v, lT, rT)
    }
  }

}

object AbTree {
  implicit private object NothingOrdering extends Ordering[Any] {
    override def compare(x: Any, y: Any): Int = 0
  }
  private object ETree extends AbTree[Any, Nothing]

  def empty[K, V]: AbTree[K, V] = ETree.asInstanceOf[AbTree[K, V]]
}

case class Tree[K, +V](key:K,
                       value:V,
                       lTree:AbTree[K,V] = AbTree.empty[K, V],
                       rTree:AbTree[K,V] = AbTree.empty[K, V])
                      (implicit ordering: Ordering[K]) extends AbTree[K,V]
类AbTree[K,+V](隐式排序:排序[K]){ def throwTreeException(msg:String)=抛出新 异常(“TreeException:+msg) def replaceL[W>:V](nTree:AbTree[K,W]):AbTree[K,W]={ val empty=AbTree.empty[K,V] 这场比赛{ case`empty`=>throwTreeException(“在ETree上调用了replaceL”) 案例树:树[K,W]=>tree.copy(lTree=nTree) } } def替换器[W>:V](nTree:AbTree[K,W]):AbTree[K,W]={ val empty=AbTree.empty[K,V] 这场比赛{ case`empty`=>throwTreeException(“在ETree上调用的替换程序”) 案例树:树[K,W]=>tree.copy(rTree=nTree) } } def插入[W>:V](nK:K,nV:W):AbTree[K,W]={ val empty=AbTree.empty[K,V] 这场比赛{ case`empty`=>树(nK,nV)//第18行 案例树(k、v、lT、rT)=> 如果(订购。比较(nK,k)<0)替换(lT.insert(nK,nV)) else if(ordering.compare(nK,k)>0)replaceR(rT.insert(nK,nV))//第21行 else树(k、v、lT、rT) } } } 对象树{ 隐式私有对象NothingOrdering扩展了排序[Any]{ 覆盖def比较(x:Any,y:Any):Int=0 } 私有对象ETree扩展AbTree[任何,无] def empty[K,V]:AbTree[K,V]=ETree.asInstanceOf[AbTree[K,V]] } 案例类树[K,+V](键:K, 值:V, lTree:AbTree[K,V]=AbTree.empty[K,V], rTree:AbTree[K,V]=AbTree.empty[K,V]) (隐式排序:排序[K])扩展了AbTree[K,V]
我可能说了一些非常愚蠢的话,因为我已经很长时间没有使用类型边界了,但是您的replace/insert方法不应该有类型签名:insert吗[L是的,现在回想起来,这并不是最好的尝试。我尝试过,但得到了另一个更隐晦的错误,所以我决定大致展示一下我想要实现的目标,看看是否有人能帮上忙。我会尝试更改这些目标,看看我得到了什么。我可能需要先巩固我的知识类型界限。我开始重新猜测我的目标“知道吗":/对于眼前的问题:
L
不一定是
订购的
,因为您只需要
L>:K
,即
K
的任何超类型。我不确定
@lmm
和code>
是订购的一部分。正如您所指出的,它们现在不起作用,因为签名不可靠。谢谢。我是c不过有几个部分在融合。类声明中的
显式
做了什么?为什么创建
方法而不是使用
case对象
?是为了绕过需要协变的两个参数吗?我以前也从未见过
asInstanceOf
,所以我必须研究一下。不是吗这似乎有点太复杂了?我本可以用Haskell编写一个完整的树实现,所需的空间足以满足上述类定义和插入方法的需要。
implict
是一件复杂的事情,但在这种情况下,这意味着Scala编译器将尝试在当前范围内找到适合该类型和插入方法的顺序t将为您提供该参数。
asInstanceOf
只是一个显式类型转换来愚弄编译器。
empty
方法只是一个“复制粘贴”方法关于Scala的地图如何处理这个问题。我知道这不是一个答案,但也许你会有一些想法。祝你好运。谢谢。我不是故意说不感激。对不起,希望在最后一件事上,它会在哪里找到“订单”?我查了隐式,对它有了基本的了解,但不知道它会在哪里找到实例。我怀疑地图的用户需要提供它,那么它是通过自动导入提供的吗?
class AbTree[K, +V](implicit ordering: Ordering[K]) {
  def throwTreeException(msg:String) = throw new
      Exception("TreeException: " + msg)

  def replaceL[W >: V](nTree:AbTree[K, W]): AbTree[K, W] = {
    val empty = AbTree.empty[K, V]
    this match {
      case `empty` => throwTreeException("replaceL called on an ETree")
      case tree:Tree[K, W] => tree.copy(lTree = nTree)
    }
  }

  def replaceR[W >: V](nTree:AbTree[K, W]): AbTree[K, W] = {
    val empty = AbTree.empty[K, V]
    this match {
      case `empty`          => throwTreeException("replaceR called on an ETree")
      case tree:Tree[K, W] => tree.copy(rTree = nTree)
    }
  }

  def insert[W >: V](nK:K,nV:W): AbTree[K,W] = {
    val empty = AbTree.empty[K, V]
    this match {
      case `empty` => Tree(nK, nV) //Line 18
      case Tree(k, v, lT, rT) =>
        if (ordering.compare(nK, k) < 0) replaceL(lT.insert(nK, nV))
        else if (ordering.compare(nK, k) > 0) replaceR(rT.insert(nK, nV)) //Line 21
        else Tree(k, v, lT, rT)
    }
  }

}

object AbTree {
  implicit private object NothingOrdering extends Ordering[Any] {
    override def compare(x: Any, y: Any): Int = 0
  }
  private object ETree extends AbTree[Any, Nothing]

  def empty[K, V]: AbTree[K, V] = ETree.asInstanceOf[AbTree[K, V]]
}

case class Tree[K, +V](key:K,
                       value:V,
                       lTree:AbTree[K,V] = AbTree.empty[K, V],
                       rTree:AbTree[K,V] = AbTree.empty[K, V])
                      (implicit ordering: Ordering[K]) extends AbTree[K,V]