Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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
Functional programming 纯函数自底向上树算法_Functional Programming_Tree_Immutability - Fatal编程技术网

Functional programming 纯函数自底向上树算法

Functional programming 纯函数自底向上树算法,functional-programming,tree,immutability,Functional Programming,Tree,Immutability,假设我想写一个算法,处理一个不可变的树数据结构,它有一个叶子列表作为输入。它需要返回一棵新树,并从这些叶子向上改变老树 我的问题是,如果叶子在列表中,如果不重建整个树检查,似乎没有办法实现这一纯功能性操作,因为您总是需要返回一个完整的新树作为操作的结果,并且您不能改变现有的树 这是函数式编程中的一个基本问题,只有使用更合适的算法才能避免,还是我遗漏了什么 编辑:我不仅希望避免重新创建整个树,而且函数算法的时间复杂度应该与变异变量相同。这取决于函数编程语言。例如,在Haskell(一种函数式编程语

假设我想写一个算法,处理一个不可变的树数据结构,它有一个叶子列表作为输入。它需要返回一棵新树,并从这些叶子向上改变老树

我的问题是,如果叶子在列表中,如果不重建整个树检查,似乎没有办法实现这一纯功能性操作,因为您总是需要返回一个完整的新树作为操作的结果,并且您不能改变现有的树

这是函数式编程中的一个基本问题,只有使用更合适的算法才能避免,还是我遗漏了什么


编辑:我不仅希望避免重新创建整个树,而且函数算法的时间复杂度应该与变异变量相同。

这取决于函数编程语言。例如,在Haskell(一种函数式编程语言)中,结果是在最后一刻计算出来的;当他们真正需要的时候

在您的示例中,假设因为您的函数创建了一个新的树,所以必须处理整个树,而实际上函数只是传递给下一个函数,并且只在必要时执行

惰性计算的一个很好的例子是Haskell中的,它通过消除数字列表中当前数字的倍数来创建素数。请注意,数字列表是无限的。取自

素数::[Integer]
素数=筛[2..]
哪里
筛子(p:xs)=p:sieve[x | x 0]
你可能喜欢阅读


到目前为止,我所看到的最有希望的(当然不是很长…)是:它基本上保留了一个单独的结构,从节点到根的反向路径,并对这个单独的结构进行局部编辑

它可以一次完成多个局部编辑,其中大部分是固定时间的,然后将它们写回树(重建到根的路径,这是唯一需要更改的节点)

拉链是一个链接(请参见标题Zippers-功能树编辑)

在OCaml中有一个实现

免责声明:我已经编程很长时间了,但几周前才开始函数式编程,直到上周才听说过树的函数式编辑问题,所以可能还有其他我不知道的解决方案


尽管如此,看起来拉链还是能满足大多数人的愿望。如果在O(logn)或以下还有其他选择,我希望听到它们。

我最近写了一个算法,它完全符合您所描述的-

它分两个阶段工作:

  • 按节点在层次结构中的深度对节点列表进行排序
  • 自下而上构造树
  • 一些警告:

    • 没有节点突变,结果是一棵不可变的树

    • 复杂度为O(n)

    • 忽略传入列表中的循环引用


    我认为这没有任何帮助,因为本文介绍的是一种自上而下的算法,它可以排除树下的整个子树,因此可以重用旧树的大部分。从根部往下看,我不知道会受到影响的叶子在哪里,所以我不能重用旧的子树。不,不是。它沿着整棵树的叶子向下走,以发现它需要在哪里进行更改,但在构建新树时,它只会重新创建树上更改的部分,并保留不变的部分。你是对的。我应该更仔细地阅读它。但这对我没有帮助,因为时间复杂性仍然是一样的。我对问题进行了编辑,使之更加精确。树的大小是多少?变异的变种也必须访问所有的节点,对吗?我不明白。早些时候你说你不知道叶子在哪里会受到影响,但现在不知何故,变异版本可以在不访问所有叶子的情况下“找到正确的叶子”?这里的算法是什么?问题很模糊。如果我真的有可能访问新树的每个节点,那么这不就是将计算复杂性转移到程序的稍后点吗?事实上,它将函数的执行转移到程序的稍后点。然而,它只在需要时动态构建新树,这似乎是一个解决方案。非常感谢:)
    primes :: [Integer]
    primes = sieve [2..]
      where
        sieve (p:xs) = p : sieve [x|x <- xs, x `mod` p > 0]