Prolog,从inorder列表重建BST树

时间:2016-05-20 11:50:06

标签: prolog dcg

我们很清楚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.

对我来说似乎不可能。

2 个答案:

答案 0 :(得分:4)

首先,让我们使用 Definite Clause Grammar )将树与列表相关联:

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.