简体   繁体   English

如何从排序流中最佳构建持久性二叉树

[英]How to best build a persistent binary tree from a sorted stream

For a side project I wanted a simple way to generate a persistent binary search tree from a sorted stream. 对于辅助项目,我想要一种简单的方法来从排序的流生成持久的二进制搜索树。 After some cursory searching I was only able to find descriptions of techniques that involved storing a sorted array where you can access any element by index. 经过一些粗略的搜索之后,我只能找到有关存储排序数组的技术的描述,在该数组中,您可以按索引访问任何元素。 I ended up writing something that works but I figured this is well trodden territory and a canonical example is probably documented somewhere (and probably has a name). 我最终写了一些行之有效的东西,但我认为这是个被践踏的领域,并且某个地方可能记录了一个规范的示例(可能有一个名称)。

The make shift code I made is included just for clarity. 为了清楚起见,包括了我制作的制造代码。 (It's also short) (也很短)

object TreeFromStream {
  sealed trait ImmutableTree[T] {
    def height: Int
  }
  case class ImmutableTreeNode[T](
    value: T,
    left: ImmutableTree[T],
    right: ImmutableTree[T]
  ) extends ImmutableTree[T] {
    lazy val height = left.height + 1
  }
  case class NilTree[T]() extends ImmutableTree[T] {
    def height = 0
  }

  @tailrec
  def treeFromStream[T](
    stream: Stream[T],
    tree: ImmutableTree[T] = NilTree[T](),
    ancestors: List[ImmutableTreeNode[T]] = Nil
  ): ImmutableTree[T] = {
    (stream, ancestors) match {
      case (Stream.Empty, _) =>
        ancestors.foldLeft(tree) { case(right, root) => root.copy(right=right) }
      case (_, ancestor :: nextAncestors) if ancestor.left.height == tree.height =>
        treeFromStream(stream, ancestor.copy(right=tree), nextAncestors)
      case (next #:: rest, _) => 
        treeFromStream(
          rest, NilTree(),
          ImmutableTreeNode(next, tree, NilTree()) :: ancestors
        )
    }
  }
}

To create a balanced tree, which I will guess you want to do, you will need to visit each node at least once. 要创建一个平衡的树(我猜想要这样做),您需要至少访问每个节点一次。 First, collect all the nodes into a buffer, and then recursively convert the buffer into a tree: 首先,将所有节点收集到缓冲区中,然后将缓冲区递归地转换为树:

  def tfs[T](stream: Stream[T]): ImmutableTree[T] = {
    val ss = scala.collection.mutable.ArrayBuffer.empty[T]
    def treeFromSubsequence(start: Int, end: Int): ImmutableTree[T] =
      if (end == start) NilTree()
      else if (end - start == 1) ImmutableTreeNode(ss(start), NilTree(), NilTree())
      else {
        val mid = (end - start) / 2
        ImmutableTreeNode(ss(mid), treeFromSubsequence(start, mid), treeFromSubsequence(mid + 1, end))
      }
    stream.foreach { x => ss += x }
    treeFromSubsequence(0, ss.length)
  }

It will visit each value exactly twice, once to collect it and once to put it into the value field of a tree. 它将精确地访问每个值两次,一次将其收集,一次将其放入树的value字段中。

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

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