Functional programming OCaml中二叉搜索树的删除

Functional programming OCaml中二叉搜索树的删除,functional-programming,ocaml,Functional Programming,Ocaml,我正在OCaml中构造二叉搜索树的操作 type ('a, 'b) bst = | Node of 'a * 'b * ('a, 'b) bst * ('a, 'b) bst | Leaf;; let rec insert k v = function | Leaf -> Node (k, v, Leaf, Leaf) | Node (k', v', left, right) -> if k < k' then Node (k', v', inser

我正在OCaml中构造
二叉搜索树的操作

type ('a, 'b) bst = 
  | Node of 'a * 'b * ('a, 'b) bst * ('a, 'b) bst
  | Leaf;;

let rec insert k v = function
  | Leaf -> Node (k, v, Leaf, Leaf)
  | Node (k', v', left, right) ->
    if k < k' then Node (k', v', insert k v left, right)
    else if k = k' then Node (k, v, left, right)
    else Node (k', v', left, insert k v right);;

let rec delete k = function
  | Leaf -> Leaf
  | Node (k', v, l, r) as p ->
    if k < k' then Node (k', v, (delete k l),r)
    else if k > k' then Node (k', v, l, (delete k r))
    else 
    match (l, r) with
      | (Leaf, Leaf) -> Leaf
      | (l, Leaf) -> l
      | (Leaf, r) -> r
      | (_, _) ->
        let Node (km, vm, _, _) = max l in
        Node (km, vm, delete km l, Leaf)
type('a,'b)bst=
|“a*”b*('a,'b)bst*('a,'b)bst的节点
|叶子;;
让rec插入k v=函数
|叶->节点(k、v、叶、叶)
|节点(k',v',左,右)->
如果k叶
|节点(k',v,l,r)作为p->
如果kk',则节点(k',v,l,(删除kr))
其他的
将(左、右)与
|(叶子,叶子)->叶子
|(左,叶)->l
|(叶,右)->r
| (_, _) ->
设节点(km,vm,u,u)=最大l in
节点(km、vm、删除km l、叶)

有人能告诉我我的
删除
代码是否足够好或者有什么改进吗?

当我们插入树中的内容,或者删除树中不存在的内容时,有一个改进。每个操作都会将搜索路径复制到该特定节点。插入可能不是问题,因为您希望更新该键的值,但删除可能是一种可以改进的情况。这可以通过使用异常包装函数以返回原始树来解决

以下是不在树中的内容的删除。在递归时,创建一个新的
节点
,并在正确的子树中删除键。在这种特殊情况下,delete函数将递归到一个
,然后返回一个
,在堆栈的每一步返回一个新构造的
节点
。此新路径表示为下面的蓝色路径。由于没有将新路径展开到旧路径的结构,我们在结果树中重新创建搜索路径

let at = delete x bt

如前所述,要解决此问题,请将函数包装在异常中

let delete k t =
    let rec delete k = function
        | Leaf -> raise Not_found
        ...
    in
    try delete k t with Not_found -> t

我想在我的例子中,如果删除找不到密钥,那么将返回相同的树,不是吗?不是。我在上面正确地描述了删除。它在结构上是同一棵树,但在物理上不是。这些递归调用在每个调用中重新构造一个新的
节点
。您可以将其视为准备一个新节点,假设我们要删除左子树(或右子树)上的某些内容。当然,这个假设是不正确的,我们最终得到了一个
,它返回一个
,但在没有删除任何内容的情况下,它绝不会将新路径解回到旧路径。这只是一种性能改进,只会在大型树或树上的数据较大的情况下发挥作用。不过,总的来说,我认为这是一个很好的例子,说明了如何正确处理递归数据结构,以及它们是如何在高层存储在内存中的。冈崎在他的书《纯功能数据结构》的练习2.3中提到了它。