处理Prolog中列表中的列表

时间:2013-12-26 14:35:49

标签: prolog

我有以下列表:

[[[...],member,[...]],Header,[[...],member,[...]]].

表示二叉搜索树。这是我在Prolog中构建二叉树的想法,但问题是:如何访问每个列表,以及如何区分它们。最重要的问题是:如何将变量'点'(我使用C语言的概念来解释我的想法)到树的标题,由标题表示。

3 个答案:

答案 0 :(得分:3)

Prolog中的区分结构是模式匹配的问题。如果我们考虑你的二叉树结构:

[[[...],member,[...]],Header,[[...],member,[...]]]

正如@ScottHunter指出的那样,它的形式为:

BinTree = [Left, Head, Right]

LeftRight是二进制树结构,再次以递归方式定义为[Left, Head, Right]Head表示节点值。我在想这就是你想要的......

假设您想要遍历二叉树( cf。 Tree Traversal)。您可以使用类似的东西以从左到右的顺序打印所有节点:

inorder([L, H, R]) :-
    inorder(L),     % L is assumed to be of the form [L,H,R]
    write(H), nl,
    inorder(R).     % R is assumed to be of the form [L,H,R]
inorder([]).

预购和后期订单只需遵循以下结构:

preorder([L, H, R]) :-
    write(H), nl,
    preorder(L),
    preorder(R).

postorder([L, H, R]) :-
    postorder(L),
    postorder(R),
    write(H), nl.

这很简单,只是遵循模式。树的结构知识隐含在代码中。假设每个分支的格式为[L, H, R],空分支为[]。所以树可能看起来像:[ [[], a, [[[],d,[]], e, []]], b, [[], c, []] ]。如果节点为空列表[],则假定该节点为空。对于这种情况,你会得到:

| ?- inorder( [ [[], a, [[[],d,[]], e, []]], b, [[], c, []] ]).
a
d
e
b
c

请注意,谓词中没有关于Head结构的假设。它本身可以是一个列表或任何其他类型的Prolog术语。唯一的结构假设是二叉树是3个项目的列表:左子树,一个头和一个右子树。假设子树递归地是二叉树。假设空树是空列表[]

要使变量“指向”某个东西,可以通过统一来实现。例如:

BinTree = [ [[], a, [[[],d,[]], e, []]], b, [[], c, []] ]

现在BinTree被实例化为树,您可以查询inorder(BinTree)并获得上面显示的结果。它也可以通过参数在谓词中完成:

unify(A, A).

如果我查询unify(BinTree, [ [[], a, [[[],d,[]], e, []]], b, [[], c, []] ]).,那么BinTree现在将使用[ [[], a, [[[],d,[]], e, []]], b, [[], c, []] ]进行实例化。

请注意,您可能希望避免使用过程语言中的概念和术语来考虑Prolog。它会引导你走上编写Prolog程序的黑暗道路,而不是声明性的,因为它是打算使用的。在Prolog中应该易于解决的问题将变得困难。

答案 1 :(得分:2)

既然您似乎是Prolog的初学者,那么建议(而不是答案):

没有必要将树表示为递归嵌套列表。相反,使用arity 3的递归嵌套术语,例如,

  • bst(Element, Left, Right)树名
  • empty表示空树词

(bst在这里代表二元搜索树)

因此,代表[1,2,3,4,5,6,7]的平衡树将是:

bst(4,
    bst(2,
        bst(1,
            empty,
            empty
        ),
        bst(3,
            empty,
            empty
        )
    ),
    bst(6,
        bst(5,
            empty,
            empty
        ),
        bst(7,
            empty,
            empty
        )
    )
)

您可以查看SWI-Prolog库library(assoc)。它使用AVL实现自平衡二叉树,但无论如何你都可以读取代码:它非常清楚,如果你不想,你不需要进行自我平衡。在SWI-Prolog的源代码树中也有一个红黑树实现,它也可以通过网页获得。

除此之外,您的问题非常清楚,很难理解您面临的确切问题是什么,因为您没有显示任何代码。

编辑:

这是一个非确定性谓词,用于检查值是否在树中,或者按递增顺序枚举值:

bst_val(bst(_, Left, _), Val) :-
    bst_val(Left, Val).
bst_val(bst(Val, _, _), Val).
bst_val(bst(_, _, Right), Val) :-
    bst_val(Right, Val).

答案 2 :(得分:1)

看起来树中的每个节点都是以下形式:

[left-subtree, header, right-subtree]

如果是这样,那么如果您有一个树T,并将其与[L,H,R]统一,L将是左子树,H将成为标题,R将是正确的子树。