common-lisp - 删除 BST 中的最小元素(将 C 转换为 Lisp)
问题描述
我已经尝试了一个多小时将以下 C 代码转换为 Lisp,以修复bst-remove
Paul Graham 的书 ANSI Common Lisp 中的 BST 代码中的函数(正如那本书的勘误表中所解释的那样,已损坏),我是完全难住了。
我一直在尝试破坏性地(也是非破坏性地)编写它,并且遇到了必须检测我想要操作的实际最小节点的问题,而不是从最终节点,而是上一层,以便我可以重新分配它。这就是指针在 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));
}
以上来源:此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))))
我真正想要的是非破坏性版本
解决方案
不可变和功能版本,非常像书中的版本,但只删除了最低值:
(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)))))
推荐阅读
- visual-studio-code - 如何在 Windows 10 上的 VSCode 上启用具有子像素抗锯齿功能的 ClearType 渲染?
- javascript - 如何在运行下一个方法之前从数组中删除一个项目?
- ios - 在 iOS 版 Chrome 中下载 Apple Pass 时出错
- python - 从 numpy.timedelta64 转换为时间间隔
- rust - 有哪些选项可用于管理错误“无法借用 `*self` 作为可变/不可变”?
- vue.js - 如何修复:this.setDynamic 不是函数
- javascript - 如何使 onkeyup 仅成为字母键?
- ios - 将 JSON 数据与单元格一起使用
- graphql - 使用 apollo graphql 客户端记录请求时间的正确方法是什么?
- reactjs - 在由上下文 API 管理的状态旁边维护类中的状态是否有意义?