Data structures 在OCaml中使用数据结构的正确方法

Data structures 在OCaml中使用数据结构的正确方法,data-structures,functional-programming,ocaml,Data Structures,Functional Programming,Ocaml,好的,我已经在OCaml中编写了一个二叉搜索树 type 'a bstree = |Node of 'a * 'a bstree * 'a bstree |Leaf let rec insert x = function |Leaf -> Node (x, Leaf, Leaf) |Node (y, left, right) as node -> if x < y then Node (y, ins

好的,我已经在OCaml中编写了一个
二叉搜索树

type 'a bstree = 
    |Node of 'a * 'a bstree * 'a bstree
    |Leaf


let rec insert x = function
    |Leaf -> Node (x, Leaf, Leaf)
    |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
键入'a bTree=
|“a*”a bstree*“a bstree”的节点
|叶子
让rec插入x=函数
|叶->节点(x,叶,叶)
|节点(y、左、右)作为节点->
如果xy那么
节点(y,左侧,插入x右侧)
其他的
节点

我猜上面的代码没有问题

使用它时,我会写字

let root=insert 4 Leaf

let root=插入5个root

这是使用/插入树的正确方法吗?

我的意思是,我想我不应该声明根,每次我再次更改变量根的值,对吗


如果是这样的话,我如何始终保留根并随时向树中插入值?

这看起来是插入树的好功能代码。它不会在插入过程中改变树,而是创建一个包含该值的新树。不可变数据的基本思想是不“保留”东西。计算值并将其传递给新函数。例如,下面是一个从列表创建树的函数:

let tree_of_list l = List.fold_right insert l Leaf
它的工作原理是将当前树传递给对
insert
的每个新调用

这样想是值得学习的,因为FP的许多好处都来自于使用不可变数据。然而,OCaml是一种混合范式语言。如果愿意,可以使用引用(或可变记录字段)在树更改值时“保留”树,就像在普通命令式编程中一样

编辑:

您可能认为以下会话显示了变量x的修改:

# let x = 2;;
val x : int = 2
# let x = 3;;
val x : int = 3
# 
但是,我们可以这样看,这是两个不同的值,它们恰好都被命名为x。因为名称相同,所以x的旧值被隐藏。但是,如果您有其他方法访问旧值,它仍然会存在。也许下面会说明事情是如何运作的:

# let x = 2;;
val x : int = 2
# let f () = x + 5;;
val f : unit -> int = <fun>
# f ();;
- : int = 7
# let x = 8;;
val x : int = 8
# f ();;
- : int = 7
# 

(希望我没有破坏你的家庭作业!)

谢谢你的回复。因此,我理解将列表转换为bst是一个过程,最终的值是树并绑定到树\u的\u列表。但是,如果列表稍后再获得一个值呢?我应该再次运行转换吗?基本上,我想问的是,我应该更改变量的值吗(代码中的树列表)?FP的本质是不更改值。这是你需要的,你的头周围!列表以后无法获取新值--它是不可变的。要进一步处理该树,您需要将其传递给新函数。好的,所以它与更改变量的值无关?简单地说,如果我有
让x=1设x=2,很好,对吧?这是两个不同的
x
s,不同的
x
。顶层在这种情况下有点误导。
remove x tree
将返回一个新的树,其中不包含
x
。如果您想回收该元素使用的空间,您必须让老树超出范围,以便垃圾收集器将其清除。
let rec adjoin a b =
    match a, b with
    | Leaf, _ -> b
    | _, Leaf -> a
    | Node (v, al, ar), _ -> Node (v, al, adjoin ar b)

let rec delete x = function
    | Leaf -> Leaf
    | Node (v, l, r) ->
        if x = v then adjoin l r
        else if x < v then Node (v, delete x l, r)
        else Node (v, l, delete x r)