Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 函数式编程中递归树遍历有困难;如何避免堆栈溢出?_Scala_Recursion_Functional Programming_Binary Tree - Fatal编程技术网

Scala 函数式编程中递归树遍历有困难;如何避免堆栈溢出?

Scala 函数式编程中递归树遍历有困难;如何避免堆栈溢出?,scala,recursion,functional-programming,binary-tree,Scala,Recursion,Functional Programming,Binary Tree,我正在努力学习Coursera上的Scala课程,我意识到我在处理递归时遇到了严重的问题,特别是以函数方式进行树遍历。为了概括这个问题(为了更广泛的相关性),我将集合定义为二叉树,单个节点要么是空的,要么是非空的,它们都扩展了自定义二叉树抽象类。如果某个节点是非空的实例,则该节点具有;左子级、右子级和类MyObj的元素 给定我在非空中实现的函数findMax: def findMax: MyObj = { // traverse left, traverse right, check wi

我正在努力学习Coursera上的Scala课程,我意识到我在处理递归时遇到了严重的问题,特别是以函数方式进行树遍历。为了概括这个问题(为了更广泛的相关性),我将集合定义为二叉树,单个节点要么是
空的
,要么是
非空的
,它们都扩展了自定义二叉树抽象类。如果某个节点是
非空的实例,则该节点具有;左子级、右子级和类
MyObj
的元素

给定我在
非空
中实现的函数
findMax

def findMax: MyObj = {

  // traverse left, traverse right, check with the candidate 
  def treeAcc(tree:MyBTSet, cand: MyObj, f: (MyObj,MyObj) => MyObj): MyObj = {
    if (tree.isEmpty) cand
    else f(treeAcc(left,cand,f), treeAcc(right,cand,f))  
  }

  treeAcc(this,elem, (t1,t2) => if (t1.text > t2.text) t1 else t2)
}
  • 为什么我的代码会导致堆栈溢出

  • 我是否遗漏了一些关于函数式编程的基本知识?我对这类集合的并集也遇到了相当严重的问题(参见我之前的问题),这被认为是微不足道的,而对并集更好的实现是“简单的一行”

    我一直听说,为了在函数式编程中取得成功,你必须改变你的思维方式。然后,当你知道事情是如何运作的,一个人应该到达涅盘,世界和平将实现,世界将是一个美丽的地方居住

    然而,到目前为止,这是纯粹的挫折。。。更糟糕的是,其他学生似乎没有那么努力,论坛上充斥着优化讨论,而我却无法清楚地了解到底发生了什么。我认为这是指以下三种选择之一:

    a) 我只是太笨了,不懂这些东西

    b) 其他学生对函数式编程有一定的了解

    c) 我做错了什么事


热烈欢迎任何有助于掌握情况的人PS:请尽量不要泄露有关解决方案的任何信息,我只想了解为什么我的代码不能按预期工作,以及我应该如何思考

您的函数堆栈溢出,因为您总是使用相同的参数调用它(即
left
right
,即
this.left
this.right
)。递归调用treeAcc时,应该使用当前节点的子树而不是根节点的子树来调用它

def treeAcc(tree:MyBTSet, cand: MyObj, f: (MyObj,MyObj) => MyObj): MyObj = {
  if (tree.isEmpty) cand
  else f(treeAcc(tree.left,cand,f), treeAcc(tree.right,cand,f))  
}

嗯,这很棘手,因为抽象类MyBTSet不存在left和right,但只有它的子类NonEmpty。