完全平衡树的简单实现(Scala)

完全平衡树的经典实现是如下图的一个数组(来自wikipedia http://en.wikipedia.org/wiki/Binary_tree)


完全平衡树的简单实现(Scala)_第1张图片

这里是从0开始计数的,所以子节点的坐标要相应的调整为2 * x - 1 和2 * x。

为了方便,计数任然从1开始。对于一个节点x,它的子节点是 2 * x和 2 * x + 1;

  1. 定义如下的Tree的数据结构:

sealed abstract class Tree[+T] {
  def addValue[U >: T <% Ordered[U]](x: U): Tree[U]
}

case class Node[+T](value: T, left: Tree[T], right: Tree[T]) extends Tree[T] {
  def addValue[U >: T <% Ordered[U]](x: U): Tree[U] = {
    if (x < value) {
      Node(value, left.addValue(x), right)
    } else if (x > value) {
      Node(value, left, right.addValue(x))
    } else {
      this
    }
  }
  override def toString = "T(" + value.toString + " " + left.toString + " " + right.toString + ")"
}

case object End extends Tree[Nothing] {
  def addValue[U <% Ordered[U]](x: U) = Node(x)
  override def toString = "."
}

这里不难理解,Tree要么是一个Node,包含左子树和右子树,要么是一个End,类似于C语言里面的Null指针。生成一棵树,可以不断的在已有的树上面调用addValue,添加节点,从而得到一个新的树。这个数据结构是不可变的,每次增加新的节点(这里没有删除的操作),都会得到一个新的tree,而原来的tree是不会改变的。为了能更方便,再为Node增加一个Companion Object。

object Node {
  def apply[T](value: T): Node[T] = Node(value, End, End)
}

2. 接下来,实现完全平衡树。完全平衡树,简单说,就是节点从上到下,从左到右依次排列。这里要利用的性质也是一再提起的,对于任何一个节点x, 其左子树是2 * x,右子树是2 * x + 1;而我们要做的就是把这个性质用代码表现出来。

object Tree {
  def completeBinaryTree[T](nodes: Int, value: T): Tree[T] = {
    def go(x: Int): Tree[T] =
      if(2 * x > nodes) Node(value)
      else if(2 * x + 1 > nodes) Node(value, go(2 * x), End)
      else Node(value, go(2 * x), go(2 * x + 1))

    go(1)
  }
}

这里使用了递归调用,代码就表现了所要做的事情。这个是我的实现版本,还有一个参考的实现,要更简洁一点。

object Tree {
  def completeBinaryTree[T](nodes: Int, value: T): Tree[T] = {
    def generateTree(addr: Int): Tree[T] =
      if (addr > nodes) End
      else Node(value, generateTree(2 * addr), generateTree(2 * addr + 1))
    generateTree(1)
  }
}


有兴趣的可以参考 http://aperiodic.net/phil/scala/s-99/p63.scala, 这是一个学习scala不错的网站。


你可能感兴趣的:(scala)