【问题标题】:Can this function be considered tail recursive?这个函数可以被认为是尾递归吗?
【发布时间】:2012-10-18 21:12:57
【问题描述】:

这是我的功能:

    //Data Structures :
    abstract class HuffmanTree
  case class Node(left: HuffmanTree, right: HuffmanTree, chars: List[Char], weight: Int) extends HuffmanTree
  case class Leaf(char: Char, weight: Int) extends HuffmanTree


  def find_char(tree: HuffmanTree, x: Char, accu: List[Int]): (Boolean, List[Int]) = {
    tree match {
      case Leaf(c, _) => ((x == c),accu)
      case Node(left, right, ll, _) =>
      (find_char(left,  x,  accu ::: List(0))._1 || find_char(right, x,  accu :::List(1))._1, accu);
    }
  }

该函数采用霍夫曼树、字符和累加器。该函数的目的是在霍夫曼树中搜索字符并对其进行编码。所以我遍历树,当我向左时,我向累加器加 0,当我向右时,我向累加器加 1。

我想知道这个函数是否是尾递归的?

我还有一个问题。当我到达Leaf 时,返回的累加器总是空的。谁能解释一下我为什么会遇到这个问题?

【问题讨论】:

  • 我回答了第一部分。您的代码目前包含语法错误。因此,很难说出其中有什么问题。
  • 改正语法错误即可。对于第二部分,返回累加器为空。
  • 最后一行的括号仍然不匹配。如果我理解得很好,那么您的问题就来自于此。你能复制/粘贴你的实际代码吗?
  • 我更新了代码。我添加了我正在使用的数据结构

标签: scala tail-recursion


【解决方案1】:

一般提示:@tailrec 注解可用于检查方法是否为尾递归。

基本上在你的情况下,它不是尾递归:在Nodecase 中,两个递归调用之间有一个|| 运算符。

考虑Int 的空列表。这很简单:在任何情况下都返回 accu 的原始值。如果您调用 find_char 时将空列表作为第二个参数,则除了空列表之外,您无法获取其他内容。

【讨论】:

  • 即使我在递归调用中更新累加器值??
  • 列表是不可变的。没有副作用。您不会“更新”累加器。您创建一个,使用原始的一个和一个元素的列表。
  • 通过更新,我的意思是在列表中添加一个新元素,我完全理解这一点。但是我通过在累加器中添加一个新元素来进行递归调用。所以当我到达时,累加器在遍历树时必须有所有的 0 和 1。不是吗?
  • 是的,但是在一行中,当您调用 (find_char || find_char, accu) 时,您会返回一个空累加器作为第二个元组元素,而不是从递归调用返回的那个
  • @tailrec 无法捕获所有内容。我(愚蠢地)不久前写了一个我认为是尾递归的方法,它甚至通过带有@tailrec 注释的编译器,但它没有进行任何真正的递归调用,因为我在类的不同实例。例如。 next.find(value) 而不是 find(next, value)。我不得不重新构造该方法以对当前节点使用显式参数,而不是仅使用this 来实际获取尾调用。
猜你喜欢
  • 2016-07-18
  • 1970-01-01
  • 2012-12-30
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多