我已经尝试了一个多小时,将以下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))))
我真正想要的是非破坏性版本
答案 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)))))