Вы должны использовать предикаты структуры, в частности emp?
: вместо (equal? lt emp)
(что также ошибочно, emp
должно быть в скобках), используйте просто (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
1018 * и действительное дерево, которое осталось после его удаления (см. values
и call-with-values
, для этого; если это поначалу слишком сложно / запутанно, выможет действительно реализовать это, как вы показали в вопросе, с get-min
и рекурсивным использованием delete
, просто так будет менее эффективно ... update: добавлена более простая реализация в код ).
Минимальным элементом будет крайний левый элемент в дереве (который гарантированно не будет пустым).Есть только два случая: ли левый дочерний элемент дерева пуст или нет.Вам не нужно обрабатывать все случаи явно, как вы.Это излишне многословно.
Кроме того, в вашем описании (и в коде) у вас есть перевернутые ветки в местах: left is всегда происходитслева, рекурсия или нет рекурсии.Должно быть:
Если x рекурсию на левом поддереве + k + на правом поддереве .Если x> k, вернуть левое поддерево + k + рекурсию на правое поддерево .Если x = k, (a) верните правое поддерево , если left пусто, (b) верните left поддерево , если right пусто, или (c) в противном случае верните left поддерево + правильное минимальное значение + (правое поддерево - минимальное значение) .