删除BST中的最小元素(将C转换为Lisp)

时间:2019-07-09 20:56:52

标签: common-lisp binary-search-tree

我已经尝试了一个多小时,将以下C代码转换为Lisp,以修复Paul Graham的ANSI Common Lisp(这在勘误表中进行了解释)的BST代码中的bst-remove函数。书,坏了),我完全陷入了困境。

我一直试图以破坏性的方式(也以非破坏性的方式)编写它,并遇到了必须检测我想操作的实际最小节点的问题,而不是最终节点,而是上一层我可以重新分配。这就是C语言中引入指针的地方,而我不知道我在Lisp中为实现相似的目的正在做什么。

您可能已经知道这一点,因为它是标准bst删除功能的一部分,但如下所示,要求是replace the smallest node with its right child

我不太担心返回分钟数。实际上,如果我们以非破坏性的方式编写此代码,那么我们要返回的是新树减去min元素,而不是min(不要介意返回多个值)。

所以,我对此完全感到困惑,并且放弃了。

ETYPE deletemin(TREE *pT) 
{
    ETYPE min;

    if ((*pT)->leftChild == NULL) { 
        min = (*pT)->element; 
        (*pT) = (*pT)->rightChild; 
        return min;
    } 
    else
        return deletemin(&((*pT)->leftChild));
}

以上来源:this pdf中的p264。

这里是有关Lisp版本的结构

(defstruct (node 
  elt (l nil) (r nil))

让我知道是否要我发布其余的BST代码。


  

想法(无效)(请参见评论中的讨论):

     
(defun delete-min (bst)
  (if (null (node-l bst))
      (if (node-r bst)
          (progn
            (setf (node-elt bst) (node-elt (node-r bst)))
            (setf (node-l   bst) (node-l   (node-r bst)))
            (setf (node-r   bst) (node-r   (node-r bst))))
          (setf bst nil))   ; <- this needs to affect the var in the calling fn
      (delete-min (node-l bst))))
     

我真正想要的是非破坏性版本

1 个答案:

答案 0 :(得分:3)

不可变的功能版本,与书中的版本非常相似,但仅删除了最低的版本:

(defun bst-remove-min (bst)
  (cond ((null bst) nil)
        ((null (node-l bst)) (node-r bst))
        (t (make-node :elt (node-elt bst)
                      :l (bst-remove-min (node-l bst)) 
                      :r (node-r bst)))))

可能会使树变异的版本。与类似的CL函数一样,您应该使用返回值。

(defun n-bst-remove-min (bst)
  (when bst
    (loop :for p := c
          :for c := bst :then child
          :for child := (node-l c)
          :unless child
            :if p
              :do (setf (node-l p) (node-r c))
                  (return bst)
            :else
              :do (return (node-r c)))))