我正在阅读Jason Hickey撰写的OCaml教程,简而言之就是提出构建树的方法:
type 'a elem = Empty | Node of 'a * 'a elem * 'a elem;;
let rec insert x = function
| Empty -> Node (x, Empty, Empty)
| Node (y, left, right) as node ->
if x < y then
Node (y, insert x left, right)
else if x > y then
Node (y, left, insert x right)
else
node;;
我是否正确理解这种方法会复制树中插入新元素的部分,并将旧树的一部分附加到此新副本中?
如果是这样,我的评估是每次插入只创建O(height(tree))
个节点吗?
这(对我来说有点不寻常)方法是否依赖于如果逐个插入多个值,GC的所有旧节点副本都会被GC有效删除?
答案 0 :(得分:3)
我是否正确理解这种方法会复制树中插入新元素的部分,并将旧树的一部分附加到此新副本中?
如果是这样,我的评估是每次插入只创建O(高度(树))节点吗?
是。如果你正确地平衡树(例如红黑树),那么这意味着插入是O(log(n))。
这(对我来说有点不寻常)方法是否依赖于如果逐个插入多个值,GC的所有旧节点副本都会被GC有效删除?
是。功能编程语言通常会产生大量短期垃圾,例如:元组,闭包和小数据类型值。但是实现被优化以使其非常便宜(例如,通过轻量级堆表示,指针碰撞分配和分代收集)。
另请注意,此方法有一个基本优势:功能数据结构自动持久,即旧版本保持有效,并且可以同时使用多个版本的数据结构。使用命令式数据结构,当您需要“恢复”旧版本时,您有两个选项:(1)预先复制整个结构,或(2)维护更改日志并向后运行。这两种选择通常比使用功能结构更昂贵,其中持久性是免费的。
请参阅Chris Okasaki关于Purely Functional Data Structures的优秀书籍,详细讨论各种功能数据结构的复杂性,摊销成本和各种其他方面。 (他的thesis涵盖了大部分相同的内容,并且可以免费获得。)