简体   繁体   English

Scala:从列表创建二叉树

[英]Scala: Create a binary Tree from List

I'm a complete beginner in Scala.我是 Scala 的完整初学者。 So my question might be quite stupid, please be patient with me.所以我的问题可能很愚蠢,请耐心等待。 I have a template for a binary tree structure:我有一个二叉树结构的模板:

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]

I want to write a function which creates a binary tree from a list.我想写一个 function 从列表中创建一个二叉树。 The first list element is the root.第一个列表元素是根。 All data left of a branch are smaller and all data right of a branch are bigger:分支左侧的所有数据都较小,分支右侧的所有数据都较大:

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

I'm not sure what I wrote wrong, but my output is always only the first List element我不确定我写错了什么,但我的 output 始终只是第一个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)
}

So in the end the correct output should be something like this:所以最后正确的 output 应该是这样的:


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

There are a few things in your code that don't seem to make a lot of sense... But more importantly, what you have written looks linear to me, and I am pretty sure you can't build a BST in linear time (if you could, you could also sort in linear time then, which would be pretty cool).你的代码中有一些东西似乎没有多大意义......但更重要的是,你写的东西对我来说看起来是线性的,我很确定你不能在线性时间内构建 BST (如果可以的话,你也可以按线性时间排序,这会很酷)。 So, it looks like rather than trying to debug this code, you are better off throwing it out, and rethinking your entire approach.因此,看起来与其尝试调试此代码,不如将其扔掉,并重新考虑整个方法。

Immutable structures don't make it particularly easy to implement non-linear things, unfortunately.不幸的是,不可变结构并不能使非线性事物的实现变得特别容易。 There are several approaches you could try here.您可以在这里尝试几种方法。 One in particular is borrowing the partition idea from the quick sort:特别是从快速排序中借用了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)))
}

This seems to work:这似乎有效:

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
    }
  }
}

Note that I divided the problem into multiple steps, first creating a Tree from a List is basically just starting with a Branch that has the root and then start adding each element in the List to that base Tree .请注意,我将问题分为多个步骤,首先从List创建Tree基本上只是从具有根的Branch开始,然后开始将List中的每个元素添加到该基础Tree
And adding an element to a Tree can also be decomposed into adding it to the left or to the right accordingly.并且将元素添加到Tree也可以相应地分解为将其添加到leftright


You can see the code running in Scastie .您可以看到在Scastie中运行的代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM