Пролог, реконструировать деревья BST из списка по порядку
Мы хорошо знаем inorder
реализация для дерева BST.
inorder(nil, []).
inorder(t(Root, L, R), List) :-
inorder(L, ListLeft),
inorder(R, ListRight),
append(ListLeft, [Root|ListRight], List).
Однако возможно ли это сделать для списка? Я имею в виду реконструировать все возможные деревья BST, например:
inorder(X, [1,2,3]).
X = t(1, nil, t(2, nil, t(3, nil, nil))));
X = t(3, t(2, t(1, nil, nil), nil), nil), nil);
X = t(2, t(1, nil, nil), t(3, nil, nil));
false.
Это кажется невозможным для меня.
2 ответа
Во-первых, давайте используем грамматику "Определенное предложение" ( dcg) для привязки деревьев к спискам:
Inorder (ноль) -> []. inorder(t(Root, L, R)) -> Симметричный (L) [Root], Симметричный (R).
Уловка, которую я теперь буду применять, описана в диссертации Ульриха Ноймеркеля в " Укрощении левой рекурсии".
"... мы добавляем другое состояние для количества токенов, которые могут использоваться вновь обнаруженными нетерминалами. Поэтому количество токенов, которые будут считываться терминалами в рамках одного правила, зарезервировано заранее".
В нашем случае:
inorder (ноль, Es, Es) -> []. inorder (t (Root, L, R), [_ | Es0], Es) -> порядок (L, Es0, Es1), [Root], Inorder (R, Es1, Es).
Пример запроса (Ls
опущены):
? - Ls = [1,2,3], фраза (inorder(Tree, Ls, _), Ls). Tree = t(1, ноль, t(2, ноль, t(3, ноль, ноль))); Tree = t(1, ноль, t(3, t(2, ноль, ноль), ноль)); Tree = t(2, t(1, ноль, ноль), t(3, ноль, ноль)); Tree = t(3, t(1, ноль, t(2, ноль, ноль)), ноль); Tree = t(3, t(2, t(1, ноль, ноль), ноль), ноль); ложный.
Другим способом решения таких проблем является использование механизма табулирования вашей системы Prolog.
Если вам нравится трюк, который я предложил здесь, единственное необходимое изменение может быть
: - use_module (carlo ( snippets / when_)).
inorder(t(Root, L, R), List) -:- ...
и сейчас
?- inorder(T,[1,2,3]).
T = t(1, nil, t(2, nil, t(3, nil, nil))) ;
T = t(1, nil, t(3, t(2, nil, nil), nil)) ;
T = t(2, t(1, nil, nil), t(3, nil, nil)) ;
T = t(3, t(1, nil, t(2, nil, nil)), nil) ;
T = t(3, t(2, t(1, nil, nil), nil), nil) ;
false.