我正在使用球拍来返回给定树的深度。这是当前的代码:
(define (depth tree)
(cond
[(empty? tree) 0]
[else
(+ 1 (max (depth (cadr tree))
(depth (caddr tree))))]))
我无法测试它,因为我总是遇到违反汽车和cdr合同的运行时错误。具体来说,当我尝试
时(depth '(1 2 3))
应该返回1,我遇到:
length: contract violation
expected: list?
given: 2
无论我做什么,问题仍然存在,我不允许更改测试用例来解决问题。我确信这很简单,但有人可以帮我理解吗?
(我查看了其他帖子;有些人讨论了深度算法,但我要具体询问此处提供的汽车/ cdr合同违规情况。)
答案 0 :(得分:0)
您的问题的答案包含在您的基本案例中:empty?
。什么是'()
?它是list
的结尾。因此,如果您想知道深度,您需要确保重复出现在相关列表中的任何列表。
以下是我在阅读代码时所要求的内容:如果tree
有一些元素,则将该元素的深度与下一个元素的深度进行比较。您可能想要问的是,使用列表其余部分的深度来获取该元素的最大深度(这不是caddr
它是cdr
) 。所以我假设你想要将2
的深度设为零(它不是一个列表)。如果是这样,您是否在cond
测试中正确列出了这种情况?嗯。也许有办法检查某些东西是否是一对,在这种情况下我们会重复,否则它的深度为0 ......
答案 1 :(得分:0)
这里可能存在一些问题。
首先也是最重要的:您粘贴的错误与“长度”有关,但程序中没有任何“长度”用法。当我运行你的代码时,这是我得到的错误:
cadr: contract violation
expected: (cons/c any/c pair?)
given: 2
了解这里发生了什么的最好方法可能是使用步进器。更具体一点:将语言级别设置为“使用列表缩写开始学生”,将以下程序放在定义窗口中,然后单击“步骤”:
(define (depth tree)
(cond
[(empty? tree) 0]
[else
(+ 1 (max (depth (cadr tree))
(depth (caddr tree))))]))
(depth '(1 2 3))
答案 2 :(得分:0)
使用pair?
代替empty?
并切换条款。给你:
(define (depth tree)
(cond
[(pair? tree)
(+ 1 (max (depth (cadr tree))
(depth (caddr tree))))]
[else 0]))
问题在于您使用cadr
和caddr
,正如您在运行给定示例时所看到的那样:
实际错误是:
cadr: contract violation
expected: (cons/c any/c pair?)
given: 2
这是因为您只检查empty?
,仅在给出空列表时返回#t
。像2
这样的数字是 NOT 一个空列表,所以它返回#f,然后移动到第二个案例,在那里你试图获取一个空列表的cadr。显然这会失败。
检查某些内容是否为pair?
可以获得您想要的实际案例。
一般来说,退一步并实际考虑你正在遍历的数据类型会更好。
例如,我可以写出:
Tree = (Cons LeftNode RightNode)
| Number
考虑到这一点,更容易看到car
和cdr
将直接访问您的孩子。
(car (Cons LeftNode RightNode)) => LeftNode
(cdr (Cons LeftNode RightNode)) => RightNode
显然,car
和cdr
的数字将会出错。
从这里可以很明显地定义你的深度函数
(define (depth tree)
(cond
[(pair? tree)
(+ 1 (max (depth (car tree))
(depth (cdr tree))))]
[else 0]))
请注意,我使用pair?
代替empty?
。如果您真的想了解这里发生了什么,我强烈建议您查看How To Design Programs,它会带您完成我在这里以更慢(更清洁)的方式使用的设计配方步骤。
如果您愿意,您甚至可以将此想法扩展为包含具有3个或4个子节点的树:
Tree = (Listof Tree Tree Tree)
| (Listof Tree Tree Tree Tree)
| Number
鉴于此,您能为具有任意数量的子树节点的树找出粗略的数据类型吗?