这是一项任务。但它已经[已经]到期,我想我已经解决了。我是Racket的新手。我觉得我的代码有点单调乏味。有没有更好的方法来改善它?
要求假设提供密钥x
,k
是根节点的值。如果x < k
,则在左子树+ k
+右子树上返回递归。如果x > k
,则在右子树+ k
+左子树上返回递归。如果x=k
,(a)返回右子树,如果左为空,(b)如果右为空则返回左子树,否则(c )返回右最小值+左子树+(右子树 - 最小值):
(define (delete x tree)
(match tree
[(emp) (emp)]
[(node k lt rt)
(cond
[(< x k) (node k (delete x lt) rt)]
[(> x k) (node k lt (delete x rt))]
[else
(cond
[(equal? lt emp) rt]
[(equal? rt emp) lt]
[else
(define (get-min tree)
(match tree
[(emp) (emp)]
[(node k (emp) (emp)) k]
[(node k lt (emp)) (get-min lt)]
[(node k (emp) rt) k]
[(node k lt rt) (get-min lt)]))
(node (get-min rt) lt (delete (get-min rt) rt))])])]))
以下是给定的树结构。我们不应该修改它。
; The empty tree is represented by an "emp" record of 0 fields.
(struct emp () #:transparent)
; A node is represented by a "node" record of key, left child, right child.
(struct node (key left right) #:transparent)
; BST insert.
(define (insert x tree)
(match tree
[(emp) (node x (emp) (emp))]
[(node k lt rt)
(cond
[(< x k) (node k (insert x lt) rt)]
[(< k x) (node k lt (insert x rt))]
[else tree])]))
答案 0 :(得分:0)
您应该使用结构谓词,特别是emp?
:而不是(equal? lt emp)
(这也是错误的,emp
应该在parens中),只使用(emp? lt)
。
当一个函数太长时,它应该被分解为更小的函数。
最后,删除和报告树的最小元素应该在一个函数中完成,一个树遍历。 delete
过于宽泛,正在寻找它所给予的元素;但是在这里我们已经知道元素将位于最左边的位置:
(define (delete x tree)
(define (join lt rt) ; all values that are in lt
(cond ; are less than those in rt
[(emp? lt) rt]
[(emp? rt) lt]
[else (call-with-values ; use rt's minimum value
(lambda () (min-elem rt)) ; as the new top node's
(lambda (k tree)
(node k lt tree) ))]))
(define (min-elem tree) ; tree is guaranteed to be non-empty
; a less efficient mock-up; better if done with one traversal
(let ([minval (get-min tree)])
(values minval (delete minval tree))))
(define (get-min tree) ; leftmost value in a non-empty tree
(match tree
[(node k (emp) _) k]
[(node _ lt _) (get-min lt)]))
(match tree
[(emp) (emp)]
[(node k lt rt)
(cond
[(< x k) (node k (delete x lt) rt)]
[(> x k) (node k lt (delete x rt))]
[else (join lt rt)])])) ; removing the top
min-elem
的责任是将两者最小元素和删除后删除的有效树(参见values
,和call-with-values
,对于那个;如果一开始太费力/混乱,你确实可以按照你在get-min
和delete
的递归使用中所显示的那样实现它,它只是效率会低一些... update:将更简单的实现添加到代码中。
最小元素将是树中的最左边(保证非空)。只有两种情况需要考虑:树的左子是否为空。您不需要像处理那样明确地处理所有情况。这是不必要的冗长。
另外,在你的描述中(以及在代码中),你已经在地方翻转了分支: left 总是在左边,递归或没有递归。它应该是:
如果x&lt; k,在左子树上返回递归 + k + 右子树。如果x> k,在右子树上返回左子树 + k + 递归。如果x = k,(a)如果left为空则返回右子树,(b)如果right为空则返回 left subtree ,或者(c)否则返回左子树 +右最小值+ (右子树 - 最小值)。