在PROLOG中找到二叉树中的元素

时间:2018-12-19 17:43:14

标签: tree prolog logic

我正在尝试使用Prolog来实现这一点,以便在二叉树中找到一个元素。

elem1(tree(Element,void,void),Element).

elem1(tree(_Element,Left,Right),N) :-
  elem1(Left,N), 
  elem1(Right,N).

因为我认为elem1会检查树的根是否是我要搜索的元素,并且此输出可以正常工作。

?- trace,elem1(tree(c,void,void),c).
Call: (9) elem1(tree(c, void, void), c) ? creep
Exit: (9) elem1(tree(c, void, void), c) ? creep
true

但是以这种递归方式:

  ?- trace,elem1(tree(4,tree(1,void,void),tree(2,void,void)),1).
  Call: (9) elem1(tree(4, tree(1, void, void), tree(2, void, void)), 1) 
  creep
  Call: (10) elem1(tree(1, void, void), 1) ? creep
  Exit: (10) elem1(tree(1, void, void), 1) ? creep
  Call: (10) elem1(tree(2, void, void), 1) ? creep
  Call: (11) elem1(void, 1) ? creep
  Fail: (11) elem1(void, 1) ? creep
  Fail: (10) elem1(tree(2, void, void), 1) ? creep
  Redo: (10) elem1(tree(1, void, void), 1) ? creep
  Call: (11) elem1(void, 1) ? creep
  Fail: (11) elem1(void, 1) ? creep
  Fail: (10) elem1(tree(1, void, void), 1) ? creep
  Fail: (9) elem1(tree(4, tree(1, void, void), tree(2, void, void)), 1) ? 
  creep

  false.

似乎以正确的方式调用了(10)并正确地检查了谓词,但是在尝试进一步扩展后给我失败了。

我不知道为什么会这样,但是基本情况运行良好,因此我认为当找到一个元素时,退出并给我真实的东西,因为基本谓词是有效的。

1 个答案:

答案 0 :(得分:1)

您的代码略有修改以显示对AND(,)的使用夸大了。

elem_01(tree(Element,void,void),Element).

elem_01(tree(_Element,Left,Right),N) :-
  (
    elem_01(Left,N)
  ,
    elem_01(Right,N)
  ).

示例:

?- elem_01(tree(4,tree(1,void,void),tree(2,void,void)),1).
false.

给出错误的结果。


使用OR(;)的正确版本。

elem_02(tree(Element,void,void),Element).

elem_02(tree(_Element,Left,Right),N) :-
  (
    elem_02(Left,N)
  ;
    elem_02(Right,N)
  ).

示例:

?- elem_02(tree(4,tree(1,void,void),tree(2,void,void)),1).
true ;
false.

在二叉树中正确找到1

?- elem_02(tree(4,tree(1,void,void),tree(2,void,void)),3).
false.

正确显示3不在树中。


显示两个子句而不是OR(;)的更正版本。

elem_03(tree(Element,void,void),Element).

elem_03(tree(_Element,Left,_),N) :-
    elem_02(Left,N).

elem_03(tree(_Element,_,Right),N) :-
    elem_02(Right,N).

示例:

?- elem_03(tree(4,tree(1,void,void),tree(2,void,void)),1).
true ;
false.

在二叉树中正确找到1

?- elem_03(tree(4,tree(1,void,void),tree(2,void,void)),3).
false.

正确显示3不在树中。


在您的问题中,树显示为

elem1(tree(4,tree(1,void,void),tree(2,void,void)),1).

例如

  4
 / \
1   2

虽然它是一棵二叉树,但它不是一个适当的二叉树,其左侧的键小于根,而右侧的键大于根。

之所以需要这样的键,是因为您可以在搜索时使用比较,从而不必搜索整个树。

您的代码有效,但是如果缺少该值,则必须搜索整个树。如果您有一棵非常大的树而没有匹配项,那么如果正确构建树并将比较结果添加到代码中,您会发现它丢失的速度要快得多。

这是适合您的示例的树:

elem1(tree(2,tree(1,void,void),tree(4,void,void)),1).

例如

  2
 / \
1   4