我们很清楚BST树的inorder
实施。
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.
对我来说似乎不可能。
答案 0 :(得分:4)
首先,让我们使用 Definite Clause Grammar ( dcg )将树与列表相关联:
inorder(nil) --> []. inorder(t(Root, L, R)) --> inorder(L), [Root], inorder(R).
我现在将应用的技巧在Ulrich Neumerkel的dissertation Taming Left Recursion 中进行了描述。
" ...我们为新遇到的非终结符号可以使用的令牌数添加另一个状态。因此,预先保留单个规则中终端将读取的令牌数量。"
在我们的案例中:
inorder(nil, Es, Es) --> []. inorder(t(Root, L, R), [_|Es0], Es) --> inorder(L, Es0, Es1), [Root], inorder(R, Es1, Es).
示例查询(省略Ls
):
?- Ls = [1,2,3], phrase(inorder(Tree, Ls, _), Ls). Tree = t(1, nil, t(2, nil, t(3, nil, nil))) ; Tree = t(1, nil, t(3, t(2, nil, nil), nil)) ; Tree = t(2, t(1, nil, nil), t(3, nil, nil)) ; Tree = t(3, t(1, nil, t(2, nil, nil)), nil) ; Tree = t(3, t(2, t(1, nil, nil), nil), nil) ; false.
解决此类问题的另一种方法是使用Prolog系统的标签机制。
答案 1 :(得分:1)
如果你喜欢我提出的here技巧,唯一需要做的改变可能是
:- 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.