微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

基于prolog中的遍历查找二叉搜索树

如何解决基于prolog中的遍历查找二叉搜索树

我正在尝试编写一个 Prolog 谓词,为给定的遍历提供可能的二叉搜索树。我选择用 t(Root,Left Subtree,Right Subtree) 来表示树,叶子只是 t(Number),当子树不存在时,它的值为 nil

这是我目前所拥有的(在这种情况下仅用于后序遍历):

post(nil,[]).
post(t(X),[X]).
post(t(N,L,R),T) :-
    post(L,TL),post(R,TR),append([TL,TR,[N]],T).

这在一个方面工作得很好,但在另一个方向上则悬而未决:

?- post(t(8,t(5,t(2),nil),t(12,t(9),t(16))),Trav).
Trav = [2,5,9,16,12,8].

?- post(Tree,[2,8]).
Tree = t(8,nil,t(16,t(9,t(2)))))) ;
Tree = t(8,t(2,nil)))))) ;
[execution hangs here]

我意识到 post 不需要二叉 search 树,即没有要求左子树中的所有节点都小于根节点和左子树中的所有节点右子树要大于根节点,所以我也这样写:

tree(t(_)).
tree(nil).
tree(t(N,R)) :-
    tree(L),tree(R),( L = t(NL,_,_) -> NL < N ; true ),( R = t(NR,_) -> NR > N ; true ).

我想我可以只做 ?- post(Tree,[...]),tree(Tree). 使 Prolog 只返回实际的二叉搜索树。然而,我似乎已经被困在生成可能的树上。

我怎样才能改进我的代码?这甚至可行吗?

解决方法

我的建议是针对不同的方向写不同的代码。这是将列表转换回树的代码。与原始代码的主要区别在于我们在重建树之前解构了列表(使用 last/3append/3)。请注意,我在第三个子句(两个 maplist/2 调用)中添加了用于检查搜索树的代码,但如果您想单独保留它们,也可以将其删除。

postlist_to_tree([],nil).
postlist_to_tree([X],t(X)).
postlist_to_tree(Xs,t(Last,LT,RT)):-
    last(Fore,Last,Xs),append(LL,RL,Fore),maplist('>='(Last),LL),maplist('=<'(Last),RL),postlist_to_tree(LL,LT),postlist_to_tree(RL,RT).

现在把它作为一个单一的谓词,我建议做这样的事情,使用一个非逻辑谓词(在这个例子中为ground/1)来决定根据参数的实例化调用哪个版本在通话时间。

post2(Tree,List):-
    ground(List),!,postlist_to_tree(List,Tree).
post2(Tree,List):-
    post(Tree,List).

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。