gpt4 book ai didi

scala - Scala的N树遍历导致堆栈溢出

转载 作者:行者123 更新时间:2023-12-04 03:22:17 27 4
gpt4 key购买 nike

我正在尝试从N树数据结构返回小部件列表。在我的单元测试中,如果我大约有大约2000个具有单个依赖项的小部件,我将遇到堆栈溢出。我认为正在发生的是for循环导致我的树遍历不是尾递归。用scala编写此代码的更好方法是什么?这是我的功能:

protected def getWidgetTree(key: String) : ListBuffer[Widget] = {
def traverseTree(accumulator: ListBuffer[Widget], current: Widget) : ListBuffer[Widget] = {
accumulator.append(current)

if (!current.hasDependencies) {
accumulator
} else {
for (dependencyKey <- current.dependencies) {
if (accumulator.findIndexOf(_.name == dependencyKey) == -1) {
traverseTree(accumulator, getWidget(dependencyKey))
}
}

accumulator
}
}

traverseTree(ListBuffer[Widget](), getWidget(key))
}

最佳答案

它不是尾递归的原因是您正在函数内进行多个递归调用。要进行尾部递归,递归调用只能是函数主体中的最后一个表达式。毕竟,关键是它的工作方式类似于while循环(因此可以转换为循环)。循环不能在一次迭代中多次调用自身。

要进行这样的树遍历,您可以使用队列来结转需要访问的节点。

假设我们有这棵树:

//        1
// / \
// 2 5
// / \
// 3 4

用这个简单的数据结构表示:
case class Widget(name: String, dependencies: List[String]) {
def hasDependencies = dependencies.nonEmpty
}

我们有指向每个节点的此映射:
val getWidget = List(
Widget("1", List("2", "5")),
Widget("2", List("3", "4")),
Widget("3", List()),
Widget("4", List()),
Widget("5", List()))
.map { w => w.name -> w }.toMap

现在我们可以将您的方法重写为尾递归的:
def getWidgetTree(key: String): List[Widget] = {
@tailrec
def traverseTree(queue: List[String], accumulator: List[Widget]): List[Widget] = {
queue match {
case currentKey :: queueTail => // the queue is not empty
val current = getWidget(currentKey) // get the element at the front
val newQueueItems = // filter out the dependencies already known
current.dependencies.filterNot(dependencyKey =>
accumulator.exists(_.name == dependencyKey) && !queue.contains(dependencyKey))
traverseTree(newQueueItems ::: queueTail, current :: accumulator) //
case Nil => // the queue is empty
accumulator.reverse // we're done
}
}

traverseTree(key :: Nil, List[Widget]())
}

并测试一下:
for (k <- 1 to 5)
println(getWidgetTree(k.toString).map(_.name))

打印:
ListBuffer(1, 2, 3, 4, 5)
ListBuffer(2, 3, 4)
ListBuffer(3)
ListBuffer(4)
ListBuffer(5)

关于scala - Scala的N树遍历导致堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13040422/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com