【发布时间】:2017-06-09 17:38:25
【问题描述】:
我正在学习 Prolog,我有一些问题要问你。我想学习如何解决这些问题而不是最终的解决方案。
作为一个新手,我对这门语言知之甚少,但我不想成为一个骗子:(
好的,所以我的问题是......
我已经定义了这样一个二叉树:
tree(ID_of_tree,root,ID_left_tree,ID_right_tree)
例如,这棵树
是这样定义的
tree(a4,6,b3,b4).
tree(b3,7,c1,c2).
tree(c1,5,d1,nil).
tree(d1,1,nil,nil).
tree(c2,3,nil,d2).
tree(d2,4,nil,nil).
tree(b4,8,c3,c4).
tree(c3,10,nil,nil).
tree(c4,11,d3,d4).
tree(d3,9,nil,nil).
tree(d4,2,nil,nil).
它们是我的事实数据库中的事实。所以我的第一个问题是,如何在这个数据库中识别一个节点 N 的父亲。例如:
?-father(3,a4,P).
P=7
?-father(6,a4,P).
false
定义谓词father/3。
father(N,Abn,P).
N= Node that I want to get its father
Abn = Tree where Im looking for. If a4, this means that is the all tree in this case.
P = Father of N.
我正在考虑使用findall/3,但我有两个问题。一个返回一个列表,我想得到一个数字或假。第二,如果必须通过递归完成,我不知道如何达到基本情况。
我认为我需要使用一些谓词,例如retract 或 asserta,但我不确定。
这是我的第一次尝试,但使用 father(3,a4,P). 的输出是错误的
father2(N,Abn,PA,PA):- =(N, PA).
father(N,Abn,P) :- tree(Abn,N,A1,_), tree(A1,PA,_,_), father2(N,A1,PA,P).
father(N,Abn,P) :- tree(Abn,N,_,A2), tree(A2,PA,_,_), father2(N,A2,PA,P).
我的第二次尝试是这样,它返回了一个很好的解决方案
father(N,Abn,P):- tree(FT,N,_,_), tree(_,P,FT,_).
father(N,Abn,P):- tree(FT,N,_,_), tree(_,P,_,FT).
这可能很好,但我对这个谓词有疑问,例如
father(3,d3,P).
P = 7
如果我在子树中查找,我应该限制搜索树
好的,我终于明白了。这是我最后的尝试和魅力。
首先,我创建了一个名为 check_tree/2 的谓词。这个谓词检查一棵树是否是其他树的子树。例如:
?- check_tree(c4,c2).
false
?-check_tree(d1,b3).
true
这是检查的代码:
check_tree(Abn1,Abn1).
check_tree(Ab1,Ab2):- tree(Ft,_,Ab1,_), check_tree(Ft,Ab2).
check_tree(Ab1,Ab2):- tree(Ft,_,_,Ab1), check_tree(Ft,Ab2).
接下来我像这样定义谓词father/3:
father(N,Abn,P):- tree(FT,N,_,_), tree(_,P,FT,_), check_tree(FT,Abn).
father(N,Abn,P):- tree(FT,N,_,_), tree(_,P,_,FT), check_tree(FT,Abn).
现在我只在节点在搜索子树内时才计算父节点。
?- father(3,b3,P).
P=7
?- father(3,c4,P).
false
特别感谢 luker 和 Will ness 的提示和耐心。
感谢您阅读此问题。
【问题讨论】:
-
一个节点只有一个“父亲”(除非您希望整个链都指向根节点),所以
findall/3在这里听起来不合适。father/3谓词的参数是什么意思?我理解a4是一个节点名称,3是一个节点值,但为什么在这个查询中两者都有?为什么不只是节点名称?你是如何从father(3, a4, P)得到P=7的?tree(b3, 7, c1, c2)不是a4的父亲,但它是c2的父亲,其值为 3。这有点令人困惑...... -
感谢您的回复。父亲/3 的参数是:父亲(节点比我想知道它的父节点,我要寻找的子树或树,节点的父亲)。这样做的目标是在 a4 中搜索,这是一棵由 b3、b4..etc 等子树组成的树。无论如何,我会在我的问题中编辑它以使其更清楚。
-
在 Prolog 中,您通常会使用递归。由于您没有尝试解决此问题,因此我不会为您编写代码,但我可以给您一些提示。一种简单的方法是使用辅助谓词:
father(Node, Tree, FatherNode, Father)(FatherNode是当前候选父节点)。最初,FatherNode具有由初始father/3调用给出的节点的值。不要使用retract或asserta。 -
感谢您的回复!这是我第一次尝试使用递归,但给了我错误。我用这个尝试编辑了我的问题:father2(N,Abn,PA,PA):- =(N, PA)。父亲(N,Abn,P):-树(Abn,N,A1,),树(A1,PA,,),父亲2(N,A1,PA,P)。父亲(N,Abn,P):-树(Abn,N,,A2),树(A2,PA,,),父亲2(N,A2,PA,P) .
-
您想要一个提示,帮助您学习如何自己编写代码。现在您需要特定代码的帮助吗?这是两个不同的问题。我回答了你原来的那个。
标签: prolog binary-tree