#tree #racket #fold
#дерево #ракетка #сгиб
Вопрос:
Я новичок в ракетке, и у меня возник этот вопрос:
- определите структуру,
node
, которая имеет следующие поля:value
,left
,middle
,right
. Эта структура представляет узлы в древовидной структуре.
Эти поля содержат значение, хранящееся в узле, левом поддереве, среднем поддереве и правом поддереве соответственно. Если поддерево не существует, то соответствующее поле должно содержатьemptyNode
, как описано ниже.- определите структуру,
emptyNode
, чтобы указать пустой узел в дереве.- Напишите функцию,
treeFold
, которая принимает функцию,f
, начальное значение,initial
, и древовидную структуру,tree
, в качестве параметров. Затем он должен выдать единственное значение, которое является результатом использованияf
для сгибания значений в дереве (с использованиемleft
,middle
, иright
поддеревьев в этом порядке). Обратите внимание, чтоf
это функция, которая принимает два параметра. Первый параметр — это значение из дерева, а второй — частично накопленный результат.
вызов функции должен быть :
(treeFold (lambda (a acc) ( a acc)) 15 tree)
дерево:
(node 7 (node 5 (emptyNode) (emptyNode) (emptyNode))
(node 20 (emptyNode) (emptyNode) (emptyNode))
(emptyNode))
вывод : 47
это то, что я делал до сих пор:
(struct node (value left middle right) #:transparent)
(struct emptyNode () #:transparent)
(define tree
(node 7
(node 5 (emptyNode) (emptyNode) (emptyNode))
(node 20 (emptyNode) (emptyNode) (emptyNode))
(emptyNode)))
(define (treeFold f initial tree)
(if (emptyNode? tree)
(emptyNode)
(node (f initial (node-value tree))
(node-left tree)
(node-middle tree)
(node-right tree))))
Как я могу получить общее количество целых листьев?
любые идеи или помощь, спасибо
редактировать: итак, основываясь на ответе и обсуждении в его комментариях, я получил новую функцию, но все еще есть ошибка, и я не смог ее найти. вот оно:
(define (treeFold f initial tree)
(cond
[(emptyNode? tree)
(f initial 0)]
[else (f (node-value tree)
(f (treeFold f
(treeFold f
(treeFold f initial
(node-left tree))
(node-middle tree))
(node-right tree))))]))
не могли бы вы сказать мне, как это исправить? Спасибо.
редактировать: окончательный код
(define (treeFold f initial tree)
(cond
[(emptyNode? tree) (f initial 0)]
[else (f (node-value tree)
(treeFold f
(treeFold f
(treeFold f initial
(node-left tree))
(node-middle tree))
(node-right tree)))]))
это работает так, как я ожидал
Комментарии:
1. все еще есть проблема с вашим новым кодом. как я обсуждаю в ответе,
collectAllStringsInWholeTree
это не сработает. нет необходимости объединятьinitial
с0
на пустом узле. почему0
? что, если мы имеем дело со строками?initial
достаточно просто, вот. за исключением этого, хорошо сделано. 🙂 он определяет обход дерева после заказа, тогда как мой ответ предполагает предварительный заказ. Я думаю, что оба в порядке, поскольку это не указано в требованиях. но поскольку он называется «начальный», я бы ожидал, что предварительный заказ будет предполагаемым. в противном случае он был бы назван «final» или что-то в этом роде.2. с числами, и
это не имеет значения, но что, если бы это было
-
так? или строки сstring-append
? тогда результаты для сгибания до и после заказа, в общем, будут разными. то(treeFold - 100 tree)
68
есть, я думаю, должны вернуться.
Ответ №1:
обновление после того, как вопрос был отредактирован с новой версией функции.
Это шаг в правильном направлении. В нем есть несколько правильных фигур и несколько неправильных фигур.
Функции похожи на коробки, которые можно соединить вместе. Материал поступает на одни провода и выходит на некоторые другие. Каждая коробка имеет свой правильный способ использования: количество проводов и материал, который он ожидает в них.
Ваша новая версия:
(define (treeFold f initial tree)
(cond
[(emptyNode? tree)
(f initial 0)]
[else (f (node-value tree) ;; (1)
(f (treeFold f ;; (2)
(treeFold f
(treeFold f initial
(node-left tree))
(node-middle tree))
(node-right tree))))]))
f
ожидает два аргумента. (f initial 0)
выглядит правильно, по крайней мере, в этом отношении. Вызов (1)
также. Но вызов f
at (2)
имеет только один аргумент, предоставленный to f
, поэтому не может быть правильным.
Далее, к смыслу этого. Три вложенных вызова treeFold
почти верны: мы «входим» в (node-left tree)
, то есть в левое поддерево, с initial
начальным значением, затем получаем результат и используем его в качестве нового начального значения для перехода в среднее поддерево и используем вычисленный результат для переходанад правым поддеревом. Неплохо. Мы закончили. Это конечный результат, который нам нужен — нет необходимости вводить его f
дальше. Таким образом, эти два вызова f
выше трех вложенных вызовов treeFold
вообще не нужны.
Кроме того, что нам делать с (node-value tree)
? Куда это вписывается? Ответ заключается в том, что оно должно быть объединено со initial
значением путем вызова f
, и результат этого должен использоваться в качестве начального значения, с которым мы переходим по левому поддереву; значение, с которого мы начинаем сгибание.
Базовый вариант также неверен. У нас уже есть initial
, почему нам нужно было бы 0
внезапно объединить его? И почему 0
? Например, мы могли бы сгибать дерево, содержащее строки, и объединение строк с числом 0
не имело бы большого смысла.
Нет, 0
будет указано в качестве начального значения при вызове treeFold
, например
(define (sumAllNumbersInWholeTree tree)
(treeFold 0 tree))
И с помощью дерева, содержащего строки, мы могли бы, например, определить
(define (collectAllStringsInWholeTree tree)
(treeFold string-append "" tree))
Далее следует начальная версия ответа. Просмотрите его (очень слегка отредактированный) пример с вашим новым пониманием. 🙂
Для
(define tree
(node 7
(node 5 (emptyNode) (emptyNode) (emptyNode))
(node 20 (emptyNode) (emptyNode) (emptyNode))
(emptyNode)))
это должно быть, согласно спецификациям,
47 == (treeFold 15 tree)
== (treeFold 15
(node 7
(node 5 (emptyNode) (emptyNode) (emptyNode))
(node 20 (emptyNode) (emptyNode) (emptyNode))
(emptyNode)))
== (treeFold
(treeFold
(treeFold ( 15 7)
(node 5 (emptyNode) (emptyNode) (emptyNode)))
(node 20 (emptyNode) (emptyNode) (emptyNode)))
(emptyNode))
== (treeFold
(treeFold
(treeFold
(treeFold
(treeFold ( 22 5) (emptyNode))
(emptyNode))
(emptyNode))
(node 20 (emptyNode) (emptyNode) (emptyNode)))
(emptyNode))
== (treeFold
(treeFold
(treeFold
(treeFold 27
(emptyNode))
(emptyNode))
(node 20 (emptyNode) (emptyNode) (emptyNode)))
(emptyNode))
== (treeFold
(treeFold
(treeFold 27
(emptyNode))
(node 20 (emptyNode) (emptyNode) (emptyNode)))
(emptyNode))
== (treeFold
(treeFold 27
(node 20 (emptyNode) (emptyNode) (emptyNode)))
(emptyNode))
.........
(запись ==
для «равно»). Это уже дает вам все, что вам нужно для полного определения, а именно:
(treeFold i (node v lt md rt))
==
(treeFold
(treeFold
(treeFold ( i v) lt)
md)
rt)
и
(treeFold i (emptyNode))
==
i
Комментарии:
1. вы сказали, что « (Сгиб дерева i (узел v lt md rt)) « даст общее количество целых листьев, верно?
2. все листья пустые, в листьях нет значений. общее количество значений в узлах
tree
равно 32.(treeFold 15 tree)
возвращает 47.3. прежде всего, вам нужно исправить свое определение
treeFold
. это все неправильно. заставьте его следовать двум правилам внизу этого ответа.4. извините, я не был ясен в своем вопросе. я имел в виду общее количество всего дерева, включая корень. функция сгиба дерева должна выглядеть следующим образом в соответствии с вопросом. итак, в соответствии с этой функцией, как я могу использовать fold, чтобы найти общее количество значений, даже если оно отличается от моего?
5. начните с вашего дерева. вам нужно 32.
(treeFold 15 tree)
возвращает 47. почему? что такое(- 47 32)
? что бы(treeFold 14 tree)
вернулось? что вы должны вызвать, чтобы получить 32? будет ли один и тот же вызов работать с любымtree
, а не только с вашим деревом?