我正在尝试使用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)并正确地检查了谓词,但是在尝试进一步扩展后给我失败了。
我不知道为什么会这样,但是基本情况运行良好,因此我认为当找到一个元素时,退出并给我真实的东西,因为基本谓词是有效的。
答案 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