【问题标题】:Decoding the huffman code without too much recursion无需太多递归即可解码霍夫曼代码
【发布时间】:2017-11-01 21:50:59
【问题描述】:

我刚刚使用 Scala 实现了 Huffman 代码。但是,我的一项功能在大文件上效果不佳。是解码函数,我用了太多递归:

def decode(tree: BinarySearchTree, bits: List[Boolean]): List[Char] = {
  def searchCharactersInBinarySearchTree(t: BinarySearchTree, b: List[Boolean]): List[Char] = t match {
    case LeafNode(ch, _) => if (b.isEmpty) List(ch) else ch :: searchCharactersInBinarySearchTree(tree, b)
    case ForkNode(l, r, _, _) => if (b.head == false) searchCharactersInBinarySearchTree(l, b.tail) else searchCharactersInBinarySearchTree(r, b.tail)
  }
  searchCharactersInBinarySearchTree(tree, bits)
}

当我有一个很小的位列表时很好,但是当我的位列表很大(超过 10000 个项目)时,它会给出 StackOverflow 错误。我只是找不到可以使用较少递归来优化它的地方。我知道问题出在叶子中的递归调用(而不是叉子)。

如何删除此递归调用但仍保持功能正常工作?

【问题讨论】:

    标签: scala huffman-code


    【解决方案1】:

    乍一看,您的实现在LeafNode 分支中缺少.tail,因此每当您点击Leaf 节点时,您只需一遍又一遍地调用相同的函数,因为bits 没有缩小.

    其次,您可以使递归函数尾递归,以便它是堆栈安全的:

    def decode(tree: BinarySearchTree, bits: List[Boolean]): List[Char] = {
      @scala.annotation.tailrec
      def searchCharactersInBinarySearchTree(t: BinarySearchTree, b: List[Boolean], acc: List[Char] = Nil): List[Char] = t match {
        case LeafNode(ch, _) => if (b.isEmpty) acc else searchCharactersInBinarySearchTree(tree, b.tail, ch :: acc)
        case ForkNode(l, r, _, _) => if (b.head == false) searchCharactersInBinarySearchTree(l, b.tail) else searchCharactersInBinarySearchTree(r, b.tail)
      }
      searchCharactersInBinarySearchTree(tree, bits)
    }
    

    请注意,tailrec 注释除了让编译器检查该方法是否实际上是尾递归之外并没有做任何事情。

    【讨论】:

    • 奇怪的是,无论输入什么,这似乎都会导致一个空的字符列表......
    猜你喜欢
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多