首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Prolog实现PreOrder树的遍历

用Prolog实现PreOrder树的遍历
EN

Stack Overflow用户
提问于 2014-11-26 22:37:56
回答 2查看 4K关注 0票数 1

我有这个PreOrder遍历树的Prolog谓词:

代码语言:javascript
复制
preOrder(nil, []).
preOrder(node(X, nil, nil), [X]).
preOrder(node(X, L, _), [X|T]) :- preOrder(L, T).
preOrder(node(X, _, R), [X|T]) :- preOrder(R, T).

问题是,它返回一个不完整的列表。例如,我得到:

代码语言:javascript
复制
?- preOrder(node(1, node(2, node(3,nil,nil), node(4,nil,nil)), node(5,nil,nil)), L). 
L = [1,2,3]

当它应该是L=[1,2,3,4,5]时。

为什么它突然停了下来?

EN

回答 2

Stack Overflow用户

发布于 2014-11-26 23:12:01

请看Prolog生成的答案。这不是一个单独的问题:

代码语言:javascript
复制
| ?- preOrder(node(1,node(2,node(3,nil,nil),node(4,nil,nil)),node(5,nil,nil)),L).
L = [1,2,3] ? ;
L = [1,2,3] ? ;
L = [1,2,3] ? ;
L = [1,2,4] ? ;
L = [1,2,4] ? ;
L = [1,2,4] ? ;
L = [1,5] ? ;
L = [1,5] ? ;
L = [1,5] ? ;
no

你的每条规则都描述了一些独立于其他部分的部分。但你需要把它们都描述在一起。

解决这个问题的最好方法是to use DCGs

票数 1
EN

Stack Overflow用户

发布于 2014-11-26 23:13:34

它突然停止了,因为您有两个递归子句,每个子句都只到树的一侧。您还有两个基本用例,尽管第二个用例不是必需的。

因此,您可以删除第二个子句,并将两个递归子句连接到一个子句中,该子句附加了两个分支的结果。

例如:

代码语言:javascript
复制
preOrder(nil, []).
preOrder(node(X, L, R), [X|T]) :- 
  preOrder(L, LT), 
  append(LT, RT, T), 
  preOrder(R, RT).

您还可以使用累加器进行遍历:

代码语言:javascript
复制
preOrder(Tree, List):-
  preOrder(Tree, [], RList),
  reverse(RList, List).

preOrder(nil, List, List).
preOrder(node(X, L, R), List, NList) :- 
    preOrder(L, [X|List], MList), 
    preOrder(R, MList, NList).

请注意,正如一位评论者所说,preOrder的这些定义不适合在给定遍历的情况下生成树。

您可能希望使用DCGs定义一个在内部使用开放列表的可逆过程:

代码语言:javascript
复制
preOrder(nil)-->[].
preOrder(node(X, L, R))-->[X], preOrder(L), preOrder(R).

您可以使用phrase/2调用它

代码语言:javascript
复制
?- phrase(preOrder(node(1, node(2, node(3,nil,nil), node(4,nil,nil)), node(5,nil,nil))), L).
L = [1, 2, 3, 4, 5].
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27151832

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档