我正在尝试创建Prolog规则,以便在Prolog中以列表形式枚举“二叉树”。我是Prolog的新手。
具有0个节点的树是一个空列表:
[]
具有1个节点的树是:
[[],[]]
具有2个节点的树有两种可能性:
[[],[[],[]]]
[[[],[]],[]]
等等。
以下是我的规则:
bintree(0,[]).
bintree(1,[[],[]]).
bintree(N,[Lc,Rc]) :-
N > 1,
bintree(N1,Lc),
bintree(N2,Rc),
N1 >= 0,
N2 >= 0,
N3 is N1+N2+1,
N==N3.
0和1的查询显然有效。对于N = 2,它打印一种可能性,但在输入分号后得到另一种可能性时出错。 N> 2的查询直接给出错误。错误总是一样的:
ERROR: >/2: Arguments are not sufficiently instantiated
我在某些网站上看到了这个错误,但我无法弄清楚导致此错误的原因。
提前感谢您的帮助。
答案 0 :(得分:3)
使用CLPFD库将有助于为生成大小提供一个干净的解决方案。然后你不需要一个不稳定的(;))integer/1
谓词,这可能有问题:
:- use_module(library(clpfd)).
bintree(0,[]).
bintree(1,[[],[]]).
bintree(N, [L, R]) :-
N #> 1,
N #= N1 + N2 + 1,
N1 #>= 0, N2 #>= 0,
bintree(N1, L), bintree(N2, R).
或更简单(感谢@ repeat'的建议):
bintree(0,[]).
bintree(N, [L, R]) :-
N #> 0,
N #= N1 + N2 + 1,
N1 #>= 0, N2 #>= 0,
bintree(N1, L), bintree(N2, R).
?- bintree(4, L).
L = [[], [[], [[], [[], []]]]] ;
L = [[], [[], [[[], []], []]]] ;
L = [[], [[[], []], [[], []]]] ;
L = [[], [[[], [[], []]], []]] ;
L = [[], [[[[], []], []], []]] ;
L = [[[], []], [[], [[], []]]] ;
L = [[[], []], [[[], []], []]] ;
L = [[[], [[], []]], [[], []]] ;
L = [[[], [[], [[], []]]], []] ;
L = [[[], [[[], []], []]], []] ;
L = [[[[], []], []], [[], []]] ;
L = [[[[], []], [[], []]], []] ;
L = [[[[], [[], []]], []], []] ;
L = [[[[[], []], []], []], []] ;
false.
?-
CLPFD是表达数字约束的一种很好的声明方式。
答案 1 :(得分:0)
我知道我在一年前发布了这个问题,但我设法在不使用任何库的情况下解决了这个问题。这是我的解决方案:
%binary tree generator
bintree(0,[]). %0 nodes - empty list
bintree(1,[[],[]]). %1 node - list containing 2 empty lists
bintree(N,[Cl,Cr]) :-
N>=2, %check only if at least 2 nodes
between(0,N,Nl), %let Nl be in [0,N]
between(0,N,Nr), %similarly for Nr
Ns is Nl+Nr+1, %total no. of nodes should add up correctly
N==Ns, %so check for that
bintree(Nl,Cl), %children should also be valid binary trees
bintree(Nr,Cr).