Представьте, что вы определили, что дерево должно отображаться следующим образом:
<1 # <<2#3> # <4#5>>>
Складывание такого дерева означает замену каждого узла ветви фактической предоставленной операцией, которую нужно выполнить по результатамрекурсивно выполнено свертывание для составляющих типа данных (здесь два дочерних узла узла, каждый из которых представляет собой дерево), например, с +
, с получением
(1 + ((2+3) + (4+5)))
Итак, дляоставляет, вы должны просто взять значения внутри них, а для ветвей, рекурсивно применить складку для каждого из двух дочерних узлов, и объединить два результата с предоставленной функцией, с которой дерево свернуто,( edit: ) При «взятии» значений из листьев вы можете дополнительно преобразовать их, применив унарную функцию.Таким образом, в целом, вашему свёртыванию понадобятся две функции, предоставленные пользователем, одна для листьев , Lf
, а другая для объединения r результатов r эвристическое свертывание древовидных составляющих (то есть ветвей) узлов ветвления , Br
.
Ваш тип данных дерева мог быть определен по-другому, например, с помощьювозможно пустые листья, и с внутренними узлами, также несущими значения.Тогда вам нужно будет указать значение по умолчанию, которое будет использоваться вместо пустых конечных узлов, и трехстороннюю комбинацию.Тем не менее, вы бы имели сгиб, определенный двумя функциями, соответствующими двум падежам определения типа данных.
Еще одно отличие, которое следует здесь осознать, это что вы сбросите, а как сложите.Т.е. вы можете сложить свое дерево линейным способом, (1+(2+(3+(4+5)))) == ((1+) . (2+) . (3+) . (4+) . (5+)) 0
, или вы можете сложить линейный список древовидным способом, ((1+2)+((3+4)+5)) == (((1+2)+(3+4))+5)
.Все дело в том, как заключить в скобки итоговое «выражение».Конечно, в классическом взгляде на сворачивание структура выражения соответствует структуре сворачиваемой структуры данных;но вариации существуют .Также обратите внимание, что операция объединения может быть не строгой, и тип " r esult", который он потребляет / производит, может выражать составной (списки и тому подобное), а также атомарный (числаи т. д.), значения.
(обновление 2019-01-26) Это повторное заключение в скобки возможно, если операция объединения является ассоциативной, например +
: (a<sub>1</sub>+a<sub>2</sub>)+a<sub>3</sub> == a<sub>1</sub>+(a<sub>2</sub>+a<sub>3</sub>)
.Тип данных вместе с такой ассоциативной операцией и элементом «ноль» (a+0 == 0+a == a
) известен как «Monoid», а понятие сворачивания в «Monoid» захватывается классом типа Foldable
.