减少深度优先树遍历的空间使用

2024-03-23

在 Haskell 中,我们可以在恒定空间中对无限列表进行过滤、求和等操作,因为 Haskell 仅在需要时生成列表节点,并且垃圾收集它完成的节点。

我希望它能与无限的树一起使用。

下面是一个相当愚蠢的程序,它生成一个无限二叉树,其中的节点代表自然数。

然后,我编写了一个函数,对这棵树进行深度优先遍历,吐出特定级别的节点。

然后我对可被 5 整除的节点进行了快速求和。

理论上,该算法可以实现O(n)的空间n的深度树O(2^n)节点。只需动态生成树,删除已完成处理的节点即可。

Haskell 确实动态生成树,但不会对看起来的节点进行垃圾收集。

下面是代码,我希望看到具有类似效果的代码,但这不需要O(2^n) space.

import Data.List (foldl')

data Tree = Tree Int Tree Tree

tree n = Tree n (tree (2 * n)) (tree (2 * n + 1))
treeOne = tree 1

depthNTree n x = go n x id [] where
  go :: Int -> Tree -> ([Int] -> [Int]) -> [Int] -> [Int]
  go 0 (Tree x _ _) acc rest = acc (x:rest)
  go n (Tree _ left right) acc rest = t2 rest where 
    t1 = go (n - 1) left acc
    t2 = go (n - 1) right t1

main = do
  x <- getLine
  print . foldl' (+) 0 . filter (\x -> x `rem` 5 == 0) $ depthNTree (read x) treeOne

Your depthNTree uses 2^n空间,因为你保持左子树通过t1当你遍历右子树时。右子树上的递归调用不应包含对左子树的引用,这是增量垃圾收集遍历的必要条件。

在这个例子中,简单的版本可以正常工作:

depthNTree n t = go n t where
  go 0 (Tree x _ _) = [x]
  go n (Tree _ l r) = go (n - 1) l ++ go (n - 1) r

Now main输入 24 使用 2 MB 空间,而原始版本使用 1820 MB。这里的最佳解决方案与上面类似,只是它使用差异列表:

depthNTree n t = go n t [] where
  go 0 (Tree x _ _) = (x:)
  go n (Tree _ l r) = go (n - 1) l . go (n - 1) r

在许多情况下,这并不比普通列表版本快多少,因为树深度约为 20-30 时,左嵌套++不是很贵。如果我们使用较大的树深度,差异会变得更加明显:

print $ sum $ take 10 $ depthNTree 1000000 treeOne

在我的计算机上,使用差异列表的运行时间为 0.25 秒,使用列表的运行时间为 1.6 秒。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

减少深度优先树遍历的空间使用 的相关文章

  • 如何减少Scala中创建的对象数量?

    我正在 Scala 中编写一个计算机图形应用程序 它使用 RGB 类返回图像中某个点的颜色 正如你可以想象的 返回颜色 RGB 对象的函数被调用了很多次 class RGB val red Int val green Int val blu
  • Haskell 程序的 -hc 配置文件中的 PINNED 是什么意思?

    我正在尝试分析我的应用程序 分析内存使用情况时 hcRTS 选项 我注意到很多内存标记为 PINNED 当与 hy内存被标记为ARR WORDS 该程序使用以下命令创建 2400 2400 双精度矩阵Data Packed Matrixhm
  • .Net Framework 4.8 和 .Net 5 之间的垃圾收集行为差异

    为了在已经发生很多次的地方检测潜在的内存泄漏 我使用了如下所示构建的测试 主要思想是拥有一个实例 不再引用它并让垃圾收集器收集它 我不想关注这是否是一种好的技术 在我的具体情况下它做得非常出色 但我想关注以下问题 下面的代码在 Net Fr
  • 在 Haskell/Yampa 和 HOOD 中调试游戏对象的输出

    我一直坚持使用 Haskell Yampa Arrows with HOOD 为我的游戏对象生成调试输出 我的引擎基本上运行一系列游戏对象 这些对象产生输出状态 线 圆 然后进行渲染 data Output Circle Position2
  • 这个作用域/闭包什么时候在 javaScript 中被垃圾回收?

    我正在做一门课程 该课程正在讨论范围 闭包并简要提到垃圾收集 课程中提出一个问题 范围保持多久 答案是 直到 不再有任何提及它 是的 所以我们基本上说的是 是的 闭包有点像对隐藏范围对象的引用 所以只要有一些函数仍然有一个闭包 范围 该范围
  • 机器和管道(或其他类似的库)之间的概念区别是什么?

    我想学习这个概念 以便我能够理解和使用诸如machines http hackage haskell org package machines 我试着跟随R nar Bjarnason 关于机器的演讲 https dl dropbox co
  • 如何在 Windows 7 中配置 cabal?

    我已经在Windows 7中安装了Haskell Platform 2012 我在控制台中编写cabal update我收到消息说有新版本的阴谋集团 我写的cabal install cabal install 安装完成后 它告诉我 cab
  • 有可能吗?:行为 t [行为 t a] -> 行为 t [a]

    有没有办法有一个Behavior t a 其中 a 在时间 t 的值是 a 中包含的值Behavior t Behavior t a 在时间 t 即 具有以下类型的函数 Behavior t Behavior t a gt Behavior
  • 在 Windows 上使用堆栈安装 SDL2 for Haskell

    我正在尝试将 SDL2 与堆栈一起使用 我跟着这些说明 https www reddit com r haskellgamedev comments 4jpthu windows sdl2 is now almost painless vi
  • Haskell 中的异构多态性(正确方法)

    让一个模块来抽象Area操作 错误的定义 class Area someShapeType where area someShapeType gt Float module utilities sumAreas Area someShape
  • Accelerate 和 Repa 是否有不同的用例?

    我一直在玩 Repa 和 Accelerate 它们都很有趣 但我不知道何时使用其中一个 何时使用另一个 他们是一起成长 是竞争对手 还是只是为了解决不同的问题 Repa 是一个用于高效数组构建和遍历的库 用 Haskell 编程并在 Ha
  • 使用通用元组函数一次进行多次折叠

    如何编写一个接受类型函数元组的函数ai gt b gt ai并返回一个函数 该函数接受类型元素的元组ai 类型的一个元素b 并将每个元素组合成一个新的元组ai 那是签名应该是这样的 f a1 gt b gt a1 a2 gt b gt a2
  • GHC 可以为 monad 转换器派生 Functor 和 Applicative 实例吗?

    我正在尝试实施MaybeT本着mtl图书馆 使用这个非编译解决方案 LANGUAGE FlexibleInstances MultiParamTypeClasses UndecidableInstances import Control M
  • 显示未定义的实例

    可以采取任何措施来为未定义的值定义 Show 实例吗 也许存在一些 GHC 扩展 我想要这样的东西 gt print 1 undefined 1 undefined 根据Haskell 2010 报告 第 9 章 http www hask
  • Haskell 中美元符号 ($) 和 id 函数之间有关系吗?

    这几天我正在读一篇评论莫纳德挑战 http mightybyte github io monad challenges 我强烈推荐给像我这样的 Haskell 初学者 我最终得到了这个线程 https news ycombinator co
  • 如何在 Windows 7 中模拟内存不足的情况

    我有一个用 C 编写的应用程序 运行良好 但有时在现场会出现错误 我们认为这些错误是由于内存不足或与垃圾收集器的交互造成的 如果有人感兴趣 这里有描述 无法将 NHibernate Impl ExpandedQueryExpression
  • 生成所有可能的树

    给定以下数据类型定义 data FormTree Empty Node FormTree FormTree deriving Show 我想编写一个函数 它生成一个无限列表 其中包含按长度排序的所有可能的树 例如节点数量 下面的代码几乎满足
  • 将系统命令的结果绑定到 Haskell 中的变量

    如何在 Haskell 中运行系统命令and将其结果 即标准输出 绑定到变量 在伪 Haskell 中 我正在寻找类似以下内容的内容 import System Process main do output lt callCommand e
  • V8 如何管理它的堆?

    我知道V8的垃圾收集在工作时 会从GC的root开始追踪 这样无法到达的对象就会被标记然后被清除 我的问题是GC是如何遍历那些对象的 必须有一个数据结构来存储所有可达或不可达的对象 位图 链接表 顺便说一句 JVM 也做同样的事情吗 艾伦秀
  • 在 Haskell 中计算移动平均线

    我正在学习 Haskell 所以我尝试实现移动平均函数 这是我的代码 mAverage Int gt Int gt Float mAverage x a fromIntegral k fromIntegral x k lt rawAvera

随机推荐

  • 如何将两组 weka 实例合并在一起

    目前 我一次将一个实例从一个数据集复制到另一个数据集 有没有办法做到这一点 使字符串映射保持完整 mergeInstances 水平工作 是否有等效的垂直合并 这是我用来将多个 arff 文件中相同结构的数据集读取到一个大型数据集中的循环的
  • 如何在JPA中定义单向OneToMany关系

    我在 JPA 中的实体映射方面遇到以下问题 我有两个实体 第一个是查找 第二个是代表实体翻译的文本 现在我需要将 Lookup 绑定到 Text 但我不希望 Text 引用 Lookup 为了使事情变得更复杂 文本在这种关系中不使用其主键
  • 将行添加到命名范围

    我在 Google 表格中有一个命名范围 A1 K14 我想做的就是在命名范围的底部添加一个新行 这似乎是一项容易的任务 使用此代码不会扩展命名范围 并且我没有收到错误消息 它确实在命名范围之外插入一个新行 这不是我想要做的 如果我改为in
  • 带有单位编号/子前提的 Google 地方自动完成建议不会出现在响应数组中

    我正在使用 Google Places API 使用 javascript 自动完成地址 当我在输入框中输入地址的单元号和街道号时 它会在建议下拉列表中显示结果 但是当我选择地址时 操作 place changed 事件的侦听器没有任何地址
  • Rails:如何向包含变音符号的收件人发送电子邮件?

    我想发送一封包含以下设置的电子邮件 def registration confirmation user recipients user username lt user email gt from Netzwerk Muensterlan
  • 内连接与何处连接

    两者之间的性能 在 Oracle 中 是否存在差异 Select from Table1 T1 Inner Join Table2 T2 On T1 ID T2 ID And Select from Table1 T1 Table2 T2
  • Hive“ANALYZE TABLE”如何从java执行

    我需要计算配置单元表中的行数 为此 我正在使用查询 ANALYZE TABLE p 7 COMPUTE STATISTICS noscan 我想通过java获取结果 我正在尝试以下操作 代码并没有运气 我得到的错误是 Exception i
  • 如何跳转到一个巨大的文本文件中的特定行?

    下面的代码是否有其他替代方案 startFromLine 141978 or whatever line I need to jump to urlsfile open filename rb 0 linesCounter 1 for li
  • 将键值对文件读入 std::map

    我有一个 Visual Studio 2008 C 03 项目 我想将键值对文件读取到 std map 中 为此 我创建了一个istreambuf pair iterator如下 typedef std map lt std string
  • 求解四变量线性方程

    问题 我需要用 Python 解这些方程 a 3b 2c 2d 1 2a b c 2d 0 3a b 2c d 1 2a c 3d 0 这样我就可以得到a b c和d的值 有没有办法可以用分数来显示它们 My code import num
  • 如何使用版本 Maven 插件更新依赖同级模块的版本

    我在更新依赖同级项目的依赖版本时遇到问题 我的简化项目设置如下 root parent tool core tool functional tests 父项目拥有所有全局属性和依赖管理 功能测试取决于工具 而工具又取决于工具核心 根pom
  • ImageView - 高度与宽度匹配吗?

    我有一个图像视图 我希望它的宽度为 fill parent 我希望它的高度是最终的宽度 例如
  • 来自相机的原始图像数据,如“645 PRO”

    不久前我已经问过这个问题并且我也得到了很好的答案 我一直在这个论坛上上下搜索 但找不到我想要的东西 真的需要 我想从相机获取原始图像数据 至目前为止 我试图从中获取 imageDataSampleBuffer 中的数据 方法 capture
  • 如何编写HQL插入查询?

    我正在努力编写一个 HQL 查询来在表中插入新记录 我已经看到了一些插入查询 如下所示 但我不想从另一个表插入数据 如下代码所示 String hql INSERT INTO Employee firstName lastName sala
  • 局部变量赋值以避免多次强制转换

    最近有一个问题询问在 Java 中将调用 getter 的结果分配给局部变量以避免多次调用同一访问器是否是一个好主意 我找不到原始帖子 但共识似乎是这通常是不必要的 因为 Hotspot 无论如何都会优化方法调用开销 然而 对于采用这种技术
  • 执行 PHP 切换每个案例多个值的最佳方法?

    你会如何执行这个 PHP switch 语句 另请注意 这些版本要小得多 我需要创建的版本将添加更多的值 版本1 switch p case home case current home current break case users o
  • 在 Camel-CXF 中将自定义 Soap-Header 设置为 pojo-message

    我的 CXF 肥皂头有问题 我使用合同优先开发方法建立了一个 cxf 项目 我想使用 cxf 组件调用 Web 服务 如下所示
  • 詹金斯 HTTPS Git

    目前正在研究自动化概念验证 所以我试图让 Jenkins 使用我们的 GIT 存储库 但在填写凭据后 我遇到了一个奇怪的错误 Failed to connect to repository Could not init C apache t
  • 在返回带有取消的 IAsyncEnumerable 的函数中迭代 IAsyncEnumerable

    正如标题所说 我必须执行以下功能 public async IAsyncEnumerable
  • 减少深度优先树遍历的空间使用

    在 Haskell 中 我们可以在恒定空间中对无限列表进行过滤 求和等操作 因为 Haskell 仅在需要时生成列表节点 并且垃圾收集它完成的节点 我希望它能与无限的树一起使用 下面是一个相当愚蠢的程序 它生成一个无限二叉树 其中的节点代表