Классическим универсальным решением этой проблемы является то, что называется структура данных "застежка-молния" .Существует несколько вариантов, но основная идея проста: учитывая вложенную структуру данных, разбирайте ее по мере прохождения, чтобы на каждом шаге у вас был «текущий» элемент и список фрагментов, представляющих, как восстановитьОстальная часть структуры данных «выше» текущего элемента.Застежка-молния, возможно, может рассматриваться как «курсор», который может перемещаться по неизменной структуре данных, заменяя части по мере необходимости, воссоздавая только те части, которые ему необходимы.
В тривиальном случае спискафрагменты - это просто предыдущие элементы списка, хранящиеся в обратном порядке, а обход - просто перемещение первого элемента одного списка в другой.
В нетривиальном, но все же простом случае двоичного дерева фрагментыкаждый состоит из значения и поддерева, идентифицированного как правое или левое.Перемещение молнии «вниз-влево» включает в себя добавление к списку фрагментов значения текущего элемента и правого дочернего элемента, делая левый дочерний элемент новым текущим элементом.Перемещение «вниз-вправо» работает аналогично, а перемещение «вверх» осуществляется путем объединения текущего элемента с первым значением и поддеревом в списке фрагментов.
Хотя основная идея молнии очень общая, построениеЗастежка-молния для конкретной структуры данных обычно требует использования специальных битов, таких как пользовательские операции обхода или конструирования, для реализации универсальной молнии.
Оригинальный документ , описывающий застежки-молнии (предупреждение,PDF) приводит пример кода в OCaml для реализации, хранящей фрагменты с явным путем через дерево.Неудивительно, что на молнии в Haskell также можно найти много материала.В качестве альтернативы построению явного пути и списка фрагментов молнии могут быть реализованы на схеме , используя продолжения .И, наконец, кажется, есть даже ориентированная на дерево молния, предоставленная Clojure .