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

Common lisp 删除BST中的最小元素(将C转换为Lisp),common-lisp,binary-search-tree,Common Lisp,Binary Search Tree,我已经尝试了一个多小时将下面的C代码翻译成Lisp,以修复Paul Graham的书ANSI Common Lisp中bst代码中的bst remove函数(正如该书勘误表中所解释的,该函数已损坏),我完全被难倒了 我一直在尝试以破坏性(也是非破坏性)的方式编写它,但遇到了一个问题,即必须检测到我想要操作的实际最小节点,而不是从最后一个节点开始,而是从上面的一个级别开始,以便我可以重新分配它。这就是C版本中指针出现的地方,我不知道我在Lisp中做了什么来达到类似的目的 您可能已经知道这一点,因为

我已经尝试了一个多小时将下面的C代码翻译成Lisp,以修复Paul Graham的书ANSI Common Lisp中bst代码中的
bst remove
函数(正如该书勘误表中所解释的,该函数已损坏),我完全被难倒了

我一直在尝试以破坏性(也是非破坏性)的方式编写它,但遇到了一个问题,即必须检测到我想要操作的实际最小节点,而不是从最后一个节点开始,而是从上面的一个级别开始,以便我可以重新分配它。这就是C版本中指针出现的地方,我不知道我在Lisp中做了什么来达到类似的目的

您可能已经知道这一点,因为它是标准bst remove函数的一部分,但根据下面的说明,要求将最小节点替换为其右子节点

我不太在意返回min。事实上,如果我们以非破坏性的方式编写它,那么我们想要返回的是新树减去min元素,而不是min(更不用说返回多个值)

所以,我完全被难住了,已经放弃了

ETYPE deletemin(树*pT)
{
ETYPE-min;
如果((*pT)->leftChild==NULL){
最小=(*pT)->元素;
(*pT)=(*pT)->右子女;
返回最小值;
} 
其他的
返回deletemin(&(*pT)->leftChild);
}
上述信息来源:p264英寸

这是Lisp版本的相关结构

(defstruct(节点
英语教学(无)(无)
如果你想让我发布更多的BST代码,请告诉我


想法(非工作)(见评论中的讨论):

(取消删除最小值(bst)
(如果为空(节点l bst))
(如果(节点r bst)
(项目
(setf(节点elt bst)(节点elt(节点r bst)))
(setf(节点l bst)(节点l(节点r bst)))
(setf(节点r bst)(节点r(节点r bst)))

(setf bst nil));不可变的功能版本,与本书中的版本非常相似,但仅删除最低值:

(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)))))

猜一猜;你可能可以复制右子对象的插槽到当前对象…@RainerJoswig我沿着这条路径走,我认为它不起作用的原因是,如果右子对象为null,那么对象本身就需要设置为null。但是做一个
(setf bst nil)
在基本情况下不会影响调用函数。那么……这是词汇变量还是动态变量的问题?@RainerJoswig我已经在上面的OP中添加了不起作用的尝试以供参考。我复制、编译并测试了的第71页的bst代码。据我所知,它在LispWorks、GCL、CCL和SBCL中运行良好。你能提供一个链接吗对于您在问题中提到的勘误表,因为我的链接中没有提到任何勘误表?您还可以提供发生错误的完整代码吗?如果您愿意,我可以在答案中复制我的代码。@peter.cntr勘误表:第一个版本对我来说很好。谢谢。我想知道我将在什么时候使用循环宏。。。