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
谓词是一个生成和测试谓词:它首先生成一棵树,然后检查它的高度。这意味着最终谓词将继续提出所有失败的高度树,但因此陷入无限循环。