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

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


205316_5oHb_922297.png

这里是从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不错的网站。


转载于:https://my.oschina.net/u/922297/blog/335167

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值