我正在Coursera的课程中,并且试图了解树上scanLeft的逻辑。 我们有以下代码:
在这里,我们将一棵树(没有中间值,仅在Leafs中具有值)作为输入,并返回一棵具有中间值(在节点中具有值)的树
def upsweep[A](t: Tree[A], f: (A,A) => A): TreeRes[A] = t match {
case Leaf(v) => LeafRes(v)
case Node(l, r) => {
val (tL, tR) = parallel(upsweep(l, f), upsweep(r, f))
NodeRes(tL, f(tL.res, tR.res), tR)
}
}
下面给出给定具有中间值的树(节点中具有值)的代码,将返回没有中间值的树(a0是树t剩余的所有元素的约简)。
def downsweep[A](t: TreeRes[A], a0: A, f : (A,A) => A): Tree[A] = t match {
case LeafRes(a) => Leaf(f(a0, a))
case NodeRes(l, _, r) => {
val (tL, tR) = parallel(downsweep[A](l, a0, f),
downsweep[A](r, f(a0, l.res), f))
Node(tL, tR) }
}
最后是scanLeft代码:
def scanLeft[A](t: Tree[A], a0: A, f: (A,A) => A): Tree[A] = {
val tRes = upsweep(t, f)
val scan1 = downsweep(tRes, a0, f)
prepend(a0, scan1)
}
我的问题是,为什么在向下扫描之前必须使用向上扫描方法? 使用upsweep,我们生成中间值,随后使用downsweep,我们“删除”(我们不需要使用)它们。
谢谢。
答案 0 :(得分:1)
实际上更仔细地看这部分
case NodeRes(l, _, r) => {
val (tL, tR) = parallel(downsweep[A](l, a0, f),
downsweep[A](r, f(a0, l.res), f))
什么是l.res?我为什么建议必须要有它?(它是在向上扫描时创建的)我建议您一步一步地画在纸上,用(_ + _)这样的简单函数,该算法的作用是什么。如果您不了解此方法,也可以轻松地逐步解决并自行解决。