【问题标题】:Scala: Create a binary Tree from ListScala:从列表创建二叉树
【发布时间】:2021-05-04 15:56:58
【问题描述】:

我是 Scala 的初学者。所以我的问题可能很愚蠢,请耐心等待。 我有一个二叉树结构的模板:

sealed trait Tree[T]
case class Leaf[T]() extends Tree[T]
case class Node[T](left: Tree[T], data :Int, right Tree[T]) extends Tree[T]

我想编写一个从列表创建二叉树的函数。第一个列表元素是根。分支左侧的所有数据都较小,分支右侧的所有数据都较大:

def listToTree[T](list: List[T]): Tree[T] 

我不确定我写错了什么,但我的输出总是只有第一个 List 元素

def setElement(x: Int, tree: Tree[Int]): Tree[Int] = tree match {
    case Node(l, e, r) => Node(l, x, r)
    case Leaf() => new Node(Leaf(), x, Leaf()) 
}
def listToTree2[T](as: List[Int], tree: Tree[Int], x: Int): Tree[Int] = tree match
{
  case Leaf() => listToTree2(as.tail, setElement(as.head, tree), x)
  case Node(left, e, right) => if(e < x) {
    right match {
      case Leaf() => listToTree2(as.tail, setElement(as.head, tree), x)
      case Node(left2, e2, right2) => if( e < e2) listToTree2(as, right, x)
      else listToTree2(as, left, x)
    }
  } else if(e > x) { 
    left match {
      case Leaf() => listToTree2(as.tail, setElement(as.head, tree), x)
      case Node(left3, e3, right3) => if( e < e3) listToTree2(as, right, x) else listToTree2(as, left, x)
    }
  } else {
    listToTree2(as.tail, tree, x)
  }
}


def listToTree[T](as: List[Int]): Tree[Int] =
{
  val tree = new Node(Leaf(), as.head, Leaf())
  listToTree2(as, tree, as.head)
}

所以最终正确的输出应该是这样的:


val list = List(3, 2, 4, 1)
assert(listToTree(list) == Branch(Branch(Branch(Leaf(),1,Leaf()),2,Leaf()))),3,Branch(Leaf(),4,Leaf()))

【问题讨论】:

    标签: scala data-structures binary-tree


    【解决方案1】:

    你的代码中有一些东西似乎没有多大意义......但更重要的是,你写的东西在我看来是线性的,我很确定你不能构建 BST在线性时间(如果可以的话,你也可以在线性时间排序,这会很酷)。因此,看起来与其尝试调试此代码,不如将其丢弃,并重新考虑整个方法。

    不幸的是,不可变结构并不能让非线性事物的实现变得特别容易。您可以在这里尝试几种方法。特别是从快速排序中借用partition 的想法:

    def makeTree(data: List[Int]): Tree[Int] = data match {
       case Nil => Leaf()
       case head :: tail => 
          val (left, right) = tail.partition(_ < head)
          Branch(makeTree(left), head, makeTree(right.filterNot(_ == head)))
    }
    

    【讨论】:

      【解决方案2】:

      这似乎有效:

      sealed trait Tree[+T] extends Product with Serializable
      final case class Branch[+T](left: Tree[T], elem: T, right: Tree[T]) extends Tree[T]
      final case object Leaf extends Tree[Nothing]
      
      object Tree {
        def addToTree[T : Ordering](tree: Tree[T])(t: T): Tree[T] = {
          import Ordering.Implicits._
          
          tree match {
            case Leaf =>
              Branch(left = Leaf, elem = t, right = Leaf)
      
            case branch @ Branch(left, elem, right) =>
              if (t <= elem) branch.copy(left = addToTree(tree = left)(t))
              else branch.copy(right = addToTree(tree = right)(t))
          }
        }
      
        def fromList[T : Ordering](data: List[T]): Tree[T] = {    
          data match {
            case root :: tail =>
              tail.foldLeft(Branch(left = Leaf, elem = root, right = Leaf) : Tree[T]) {
                case (acc, t) =>
                  addToTree(acc)(t)
              }
            
            case Nil =>
              Leaf
          }
        }
      }
      

      请注意,我将问题分为多个步骤,首先从 List 创建一个 Tree 基本上只是从具有根的Branch 开始,然后开始将 List 中的每个元素添加到基础 Tree
      并且将元素添加到 Tree 也可以分解为将其添加到 leftright 相应地。


      可以看到Scastie中运行的代码

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多