【问题标题】:Create all possible AVL trees given a list of elements in Prolog给定 Prolog 中的元素列表,创建所有可能的 AVL 树
【发布时间】:2020-05-01 03:20:18
【问题描述】:

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

?- avl_tree_planter(X, [yin, yang]).
X = tree(yang, tree(yin, nil, nil), nil) ;
X = tree(yin, tree(yang, nil, nil), nil) ;
X = tree(yin, nil, tree(yang, nil, nil)) ;
X = tree(yang, nil, tree(yin, nil, nil)) ;

我尝试使用中序、前序和后序遍历输出所有可能的选项:

abs_diff(L,R,D) :- D is L-R, L >= R.
abs_diff(L,R,D) :- D is R-L, R >= L.

height(nil,0).
height(tree(_,L,R), H) :- 
    height(L,HL), height(R,HR), 
    max_num(HL,HR,MaxH), H is MaxH + 1.

avl_tree_planter(nil,[]).
avl_tree_planter(tree(X,L,R), Xs) :-
    height(L,HL), height(R,HR),
    abs_diff(HL,HR,Diff), Diff =< 1, 
    avl_tree_planter(L,Ls), avl_tree_planter(R,Rs), 
    append(Ls,[X|Rs],Xs).     % inorder
avl_tree_planter(tree(X,L,R), Xs) :-  
    height(L,HL), height(R,HR),
    abs_diff(HL,HR,Diff), Diff =< 1,
    avl_tree_planter(L,Ls), avl_tree_planter(R,Rs), 
    append(Rs, [X], Xs1),     % postorder
    append(Ls, Xs1, Xs).  
avl_tree_planter(tree(X,L,R), Xs) :-  
    height(L,HL), height(R,HR),
    abs_diff(HL,HR,Diff), Diff =< 1,
    avl_tree_planter(L,Ls), avl_tree_planter(R,Rs), 
    append([X|Ls], Rs, Xs).   % preorder

在一些在线解释器中输入:

avl_tree_planter(X,[a,b]).

它输出:

X = tree(a, nil, tree(b, nil, nil))

12 次然后进入无限循环,再一次无限循环。

我已经为递归设置了停止条件,那么我做错了什么?

【问题讨论】:

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

标签: recursion tree prolog binary-tree avl-tree


【解决方案1】:

之所以会出现在无限循环中,是因为您的 height/2 使用了 generate-and-test 方法:它首先构造一棵树,然后验证高度是否与要求的高度。但是随着树越来越大,最终您的检查将开始拒绝这些树,但没有办法告诉您的谓词停止提议新树。

我们可以构造每个节点最多相差一个的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.

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-30
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    相关资源
    最近更新 更多