项目被插入两次(进入两个子树)。原因不明

时间:2012-03-27 10:50:26

标签: tree prolog insertion

我编写了一个将元素插入树中的函数,然后返回新树。它采取以下形式:

% insert(Element, OldTree, NewTree)
?-insert(2, tree(nil, 5, nil), T).

并且理论上应该返回:

T = tree(tree(nil, 2, nil) 5, nil)

简单地说,将两者添加到左子树中,并添加nils以使其成为二进制。但是,在我的实现中,这两个被添加到左右子树。条件总是被违反;如果2是6,它仍然被添加到两个子树中,而不仅仅是右边。

我已经查看了这段代码一个小时,但找不到错误。一双新鲜的眼睛可以掠过这个吗?

tree(Left, Root, Right).

insert(Item, Oldtree, Newtree).

%tree is empty
insert(Element, Empty, tree(Empty, Element, Empty)):-!.

%tree isn't empty. if NewItem is less than Root, we put it on the left subtree
insert(NewItem, tree(LeftSubtree, Root, RightSubtree), tree(NewLeftSubtree, Root, RightSubtree)):-
        NewItem < Root,
    !,
        insert(NewItem, LeftSubtree, NewLeftSubtree).

%else
insert(NewItem, tree(LeftSubtree, Root, RightSubtree), tree(LeftSubtree, Root, NewRightSubtree)):-
    NewItem > Root,
    !,
        insert(NewItem, RightSubtree, NewRightSubtree).

1 个答案:

答案 0 :(得分:1)

首先,不要这样做:

tree(Left, Root, Right).

这将tree定义为(相当无用的)谓词。您不需要在Prolog中声明数据类型。

接下来,

insert(Item, Oldtree, Newtree).

insert/3定义为始终成功的谓词。你不需要这个条款。

insert(Element, Empty, tree(Empty, Element, Empty)):-!.

不按照你的想法行事; Empty是一个变量,因此它匹配任何内容。

最后,使用if-then-else:

,而不是所有复杂的切割逻辑
insert(X, tree(L0,Y,R0), tree(L,Y,R)) :-
    (X < Y ->
        % insert into left subtree
    ; X > Y ->
        % insert into right subtree
    ;
        % equals case
    ).