Recursion 在Prolog中给定元素列表,创建所有可能的AVL树

Recursion 在Prolog中给定元素列表,创建所有可能的AVL树,recursion,tree,prolog,binary-tree,avl-tree,Recursion,Tree,Prolog,Binary Tree,Avl Tree,给定一个元素列表,返回所有可能的平衡二叉树,该二叉树正好包含该列表中的元素。在我们的例子中,一个有效的树是这样构造的:tree(\uz,left,right)。例如: ?- height(T, 2, N). T = tree(_622, tree(_642, nil, nil), tree(_662, nil, nil)), N = [_622, _642, _662] ; T = tree(_622, tree(_642, nil, nil), nil), N = [_622, _642] ;

给定一个元素列表,返回所有可能的平衡二叉树,该二叉树正好包含该列表中的元素。在我们的例子中,一个有效的树是这样构造的:
tree(\uz,left,right)
。例如:

?- height(T, 2, N).
T = tree(_622, tree(_642, nil, nil), tree(_662, nil, nil)),
N = [_622, _642, _662] ;
T = tree(_622, tree(_642, nil, nil), nil),
N = [_622, _642] ;
T = tree(_622, nil, tree(_642, nil, nil)),
N = [_622, _642] ;
false.
?-avl_tree_planter(X,[阴,阳])。
X=树(阳,树(阴,无,无),无);
X=树(阴,树(阳,无,无),无);
X=树(阴,无,树(阳,无,无));
X=树(阳,无,树(阴,无,无));
我尝试使用顺序、前序和后序遍历输出所有可能的选项:

abs_diff(L,R,D):-D是L-R,L>=R。 abs_diff(L,R,D):-D是R-L,R>=L。 高度(零,0)。 高度(树高、树高、树高):- 高度(L,HL),高度(R,HR), max_num(HL,HR,MaxH),H是MaxH+1。 avl_tree_planter(无,[])。 avl_tree_播种机(树(X,L,R),Xs):- 高度(L,HL),高度(R,HR), abs_diff(HL,HR,diff),diff=<1, avl_树_种植机(L,Ls),avl_树_种植机(R,Rs), 附加(Ls[X | Rs],Xs)。%有序 avl_树播种机(树(X,L,R,Xs):- 高度(L,HL),高度(R,HR), abs_diff(HL,HR,diff),diff=<1, avl_树_种植机(L,Ls),avl_树_种植机(R,Rs), 追加(Rs,[X],Xs1),%postorder 追加(Ls、Xs1、Xs)。 avl_树播种机(树(X,L,R,Xs):- 高度(L,HL),高度(R,HR), abs_diff(HL,HR,diff),diff=<1, avl_树_种植机(L,Ls),avl_树_种植机(R,Rs), 附加([X | Ls],Rs,Xs)。%预购 在一些用于输入的在线解释器中:

avl_tree_planter(X[a,b])。
它输出:

X=tree(a,nil,tree(b,nil,nil))
十二次,然后进入无限循环,在另一个循环中无限循环


我给递归设置了一个停止条件,那么我做错了什么呢?

这在infinte循环中得到stuc的原因是因为您的
height/2
使用了一种生成和测试方法:它首先构造一棵树,然后验证高度是否与所需高度匹配。但随着树越来越大,最终您的检查将开始拒绝这些树,但无法告诉谓词停止建议新树

我们可以构造AVL树,其中每个节点的差异最多为一,如下所示:

:- use_module(library(clpfd)).

height(nil, 0).
height(tree(_, L, R), H) :-
    H #> 0,
    H1 #= H-1,
    H2 #= H-2,
    (
        (height(L, H1), height(R, H1));
        (height(L, H1), height(R, H2));
        (height(L, H2), height(R, H1))
    ).
现在我们可以生成树,并用额外的元素“标记”这些树的节点。它可能有助于生成一个更通用的谓词
height/3
,导出变量列表:

height(T, H, N) :-
    height(T, H, N, []).

height(nil, 0, N, N).
height(tree(X, L, R), H, [X|Ni], No) :-
    H #> 0,
    H1 #= H-1,
    H2 #= H-2,
    (
        (height(L, H1, Ni, Nt), height(R, H1, Nt, No));
        (height(L, H1, Ni, Nt), height(R, H2, Nt, No));
        (height(L, H2, Ni, Nt), height(R, H1, Nt, No))
    ).
例如:

?- height(T, 2, N).
T = tree(_622, tree(_642, nil, nil), tree(_662, nil, nil)),
N = [_622, _642, _662] ;
T = tree(_622, tree(_642, nil, nil), nil),
N = [_622, _642] ;
T = tree(_622, nil, tree(_642, nil, nil)),
N = [_622, _642] ;
false.

我把用列表中的元素标记树作为练习。

问题之一是,
height/2
谓词是一个生成和测试谓词:它首先生成一棵树,然后检查它的高度。这意味着最终谓词将继续提出所有失败的高度树,但因此陷入无限循环。