【问题标题】:How to write this predicate regarding trees in prolog?如何在序言中编写有关树的谓词?
【发布时间】:2016-12-03 03:46:28
【问题描述】:

如果X 是存储在树T 中的最大数,我需要帮助来定义序言谓词treeMax(T,X),而不使用“is”谓词。

我使用函数术语来表示树:node1(X,T) 表示存储数字 X 并有一个子节点 node2(X,T1,T2)node3(X,T1,T2,T3) 的节点 术语leaf(X) 表示存储编号X 的叶子。

例如:node2(1,leaf(1),node3(9,leaf(9),leaf(10),leaf(11))) 是一棵树。

感谢您的帮助:)

编辑:最大子节点数为 3:因此可能的数据库是 node1(X,T)node2(X,T1,T2)node3(X,T1,T2,T3)leaf(X)

【问题讨论】:

    标签: prolog


    【解决方案1】:

    抱歉,我认为leaf/1node1/2node2/3node3/4 解决方案不是一个好的解决方案。

    开发maxTree/2 很简单,但是...

    treeMax(leaf(M), M).
    
    treeMax(node1(V0, N1), M) :-
      treeMax(N1, V1),
      M is max(V0, V1).
    
    treeMax(node2(V0, N1, N2), M) :-
      treeMax(N1, V1),
      treeMax(N2, V2),
      M is max(V0, max(V1, V2)).
    
    treeMax(node3(V0, N1, N2, N3), M) :-
      treeMax(N1, V1),
      treeMax(N2, V2),
      treeMax(N3, V3),
      M is max(V0, max(V1, max(V2, V3))).
    

    ...但是,如您所见,对于node4/5,您必须开发另一个treeMax 子句,另一个用于node5/6,另一个用于node6/7,usw。

    建议:保持节点和叶子之间的区别,但对于节点,只实现一个带有值的结构体和一个子节点列表

    所以你对子节点的数量没有限制;所以您的maxTree/2 不需要与更多子树的附加子句集成。

    所以你的例子变成了

    node(1, [leaf(1), node(9, [leaf(9), leaf(10), leaf(11)])])
    

    maxTree/2 变成

    treeMax(leaf(M), M).
    
    treeMax(node(V0, LN), M) :-
      treeMax(LN, V1),
      M is max(V0, V1).
    
    treeMax([N], M) :-
      treeMax(N, M).
    
    treeMax([Nh | Nt], M) :-
      treeMax(Nh, V0),
      treeMax(Nt, V1),
      M is max(V0, V1).
    

    --- 编辑---

    抱歉:我现在看到您的“不使用 'is' 谓词”。

    这是一个奇怪的要求,但可以做到。

    你的解决方案很痛苦(leaf/1node1/2node2/3node3/4);我之前的解决方案变成了

    treeMax(leaf(M), M).
    
    treeMax(node1(V0, N1), V0) :-
      treeMax(N1, V1),
      V1 =< V0.
    
    treeMax(node1(V0, N1), V1) :-
      treeMax(N1, V1),
      V1 > V0.
    
    treeMax(node2(V0, N1, N2), V0) :-
      treeMax(N1, V1),
      treeMax(N2, V2),
      V1 =< V0,
      V2 =< V0.
    
    treeMax(node2(V0, N1, N2), V1) :-
      treeMax(N1, V1),
      treeMax(N2, V2),
      V1 >  V0,
      V2 =< V1.
    
    treeMax(node2(V0, N1, N2), V2) :-
      treeMax(N1, V1),
      treeMax(N2, V2),
      V2 > V0,
      V2 > V1.
    
    treeMax(node3(V0, N1, N2, N3), V0) :-
      treeMax(N1, V1),
      treeMax(N2, V2),
      treeMax(N3, V3),
      V1 =< V0,
      V2 =< V0,
      V3 =< V0.
    
    treeMax(node3(V0, N1, N2, N3), V1) :-
      treeMax(N1, V1),
      treeMax(N2, V2),
      treeMax(N3, V3),
      V1 >  V0,
      V2 =< V1,
      V3 =< V1.
    
    treeMax(node3(V0, N1, N2, N3), V2) :-
      treeMax(N1, V1),
      treeMax(N2, V2),
      treeMax(N3, V3),
      V2 >  V0,
      V2 >  V1,
      V3 =< V2.
    
    treeMax(node3(V0, N1, N2, N3), V3) :-
      treeMax(N1, V1),
      treeMax(N2, V2),
      treeMax(N3, V3),
      V3 > V0,
      V3 > V1,
      V3 > V2.
    

    如您所见,leaf/1 需要一个 treeMax/2 子句,node1/2 需要两个子句,node2/3 需要三个子句,等等。 nodeN/N+1 需要 N+1 子句。

    如果您使用基于单个 node/2 结构的解决方案,并带有子节点列表,那么我之前的解决方案将变为

    treeMax(leaf(M), M).
    
    treeMax(node(V0, LN), V0) :-
      treeMax(LN, V1),
      V1 =< V0.
    
    treeMax(node(V0, LN), V1) :-
      treeMax(LN, V1),
      V1 > V0.
    
    treeMax([N], M) :-
      treeMax(N, M).
    
    treeMax([Nh | Nt], V0) :-
      treeMax(Nh, V0),
      treeMax(Nt, V1),
      V1 =< V0.
    
    treeMax([Nh | Nt], V1) :-
      treeMax(Nh, V0),
      treeMax(Nt, V1),
      V1 > V0.
    

    【讨论】:

    • 对不起,我的意思是孩子的最大数量是3,我必须用node1,node2,node3和leaf来做
    • @delson1337 - 即便如此我认为这是一个坏主意;考虑到您的“没有谓词”要求,我已经改进了我的答案;看看基于node1/2node2/3node3/4的解决方案有多痛苦。
    【解决方案2】:

    这是一个比@max66 更简单的解决方案,在树上“折叠”max/3 谓词。简化来自使用累加器参数来存储中间结果。

    tree_max(Tree, Max) :-
        tree_max(Tree, 0, Max).
    
    tree_max(leaf(N), Acc, Max) :-
        max(N, Acc, Max).
    tree_max(node1(Value, Subtree), Acc, Max) :-
        max(Value, Acc, Acc1),
        tree_max(Subtree, Acc1, Max).
    tree_max(node2(Value, Left, Right), Acc, Max) :-
        max(Value, Acc, Acc1),
        tree_max(Left, Acc1, Acc2),
        tree_max(Right, Acc2, Max).
    tree_max(node3(Value, Child1, Child2, Child3), Acc, Max) :-
        max(Value, Acc, Acc1),
        tree_max(Child1, Acc1, Acc2),
        tree_max(Child2, Acc2, Acc3),
        tree_max(Child3, Acc3, Max).
    
    max(A, B, Max) :-
        Max is max(A, B).
    

    max/3 的这个实现确实使用了is/2,但是 (a) 这是一个愚蠢的人为约束,并且 (b) 在没有 is/2 的情况下很容易重写 max/3。整个事情也可以(并且应该)推广到一般的tree_fold/4 谓词。

    一些测试:

    ?- tree_max(node2(1,leaf(1),node3(9,leaf(9),leaf(10),leaf(11))), Max).
    Max = 11.
    
    ?- tree_max(node2(1,leaf(1),node3(9,leaf(9),leaf(10),leaf(7))), Max).
    Max = 10.
    
    ?- tree_max(node2(1,leaf(1),node3(9,leaf(42),leaf(10),leaf(7))), Max).
    Max = 42.
    
    ?- tree_max(node2(1,leaf(23),node3(9,leaf(3),leaf(10),leaf(7))), Max).
    Max = 23.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多