【问题标题】:Trying to print out preOrder Traversal in prolog试图在序言中打印出 preOrder Traversal
【发布时间】:2018-12-15 14:47:12
【问题描述】:

我正在 prolog 中实现一个二叉搜索树,并尝试为每个遍历类型 preOrder、inOrder 和 postOrder 打印输出。

我的测试树是: bst(bst(bst(empty,2,empty),4,empty),5,bst(bst(empty,6,empty),8,empty)).

这是我目前所拥有的:

preOrder(bst(_,X,_)) :- write(X).
preOrder(bst(L,_,_)) :- preOrder(L).
preOrder(bst(_,_,R)) :- preOrder(R).

它可以工作,但用户必须按空格来获取每个元素。

5
True
4
True
2
True
8
True
6
False

我希望它以5 4 2 8 6 的形式打印出来

所以我把上面的代码修改为:

preOrder(bst(L,X,R)) :- write(X), write(" "), preOrder(L), preOrder(R).

现在它只打印出5 4 2 false

我对 prolog 很陌生,谁能解释为什么将单个谓词添加到一个谓词与 3 个单独的谓词的作用不同?

【问题讨论】:

  • 最好使用dcg进行遍历

标签: prolog binary-search-tree preorder


【解决方案1】:

为什么将单个谓词添加到单个谓词与 3 个单独谓词的作用不同?

具有多个子句的谓词(您称为单个谓词)被评估为OR,而具有由, 分隔的多个语句的单个子句谓词被评估为AND

如果你改变这个

preOrder(bst(L,X,R)) :-
    write(X),
    write(" "),
    preOrder_04(L),
    preOrder_04(R).

也可以写成

preOrder(bst(L,X,R)) :-
    write(X),
    write(" "),
    (
        preOrder_04(L)
    ,
        preOrder_04(R)
    ).

preOrder(bst(L,X,R)) :-
    write(X),
    write(" "),
    (
        preOrder_04(L)
    ;
        preOrder_04(R)
    ).

那么你会得到你想要的。


由于您是 Prolog 的新手,因此我还将对您的代码进行审查。

使用您的原始树和谓词

bst(bst(bst(empty,2,empty),4,empty),5,bst(bst(empty,6,empty),8,empty))

preOrder(bst(_,X,_)) :- write(X).
preOrder(bst(L,_,_)) :- preOrder(L).
preOrder(bst(_,_,R)) :- preOrder(R).

我做了这个

tree(bst(bst(bst(empty,2,empty),4,empty),5,bst(bst(empty,6,empty),8,empty))).

test_01 :-
    tree(T),
    preOrder_01(T).

preOrder_01(bst(_,X,_)) :- write(X).
preOrder_01(bst(L,_,_)) :- preOrder_01(L).
preOrder_01(bst(_,_,R)) :- preOrder_01(R).

tree(T) 行将树作为事实读取,然后将树绑定到变量 T,这样我就不必每次都输入它。

然后我创建了一个名为 _01 的测试谓词,这样我就不会与即将到来的其他测试发生冲突。

示例运行:

?- test_01.
5
true ;
4
true ;
2
true ;
8
true ;
6
true ;
false.

为什么每次回答后都要按空格键?

(这是使用 SWI-Prolog 完成的)。

这个例子说明了原因。

test_02 :- write("First").
test_02 :- write("Second").

?- test_02.
First
true ;
Second
true.

每次执行谓词test_02/0 都会产生一个解决方案,当给出一个解决方案时,您必须按空格键才能看到下一个解决方案。

还要注意第一个答案末尾的;。这是 Prolog 告诉你存在一个选择点,可能还有另一个答案。如果是.,那么就没有更多的答案了。


对于你的重写不起作用

preOrder_03(bst(L,X,R)) :-
    write(X),
    write(" "),
    preOrder_03(L),
    preOrder_03(R).

test_03 :-
    tree(T),
    preOrder_03(T).

示例运行:

?-  test_03.
5 4 2 
false.

如果您使用跟踪运行它,您会发现它没有到达选择点。
What is redo in Prolog when you trace?


但是如果你这样做

preOrder_04(bst(L,X,R)) :-
    write(X),
    write(" "),
    (
        preOrder_04(L)
    ;
        preOrder_04(R)
    ).

test_04 :-
    tree(T),
    preOrder_04(T).

示例运行:

?- test_04.
5 4 2 8 6 
false.

你会得到你想要的。 preOrder_03preOrder_04 之间的主要区别在于,preOrder_03 在一个地方有一个,,而preOrder_04 在一个地方有一个;。逗号 (,) 是逻辑 AND,分号 (;) 是逻辑 OR

【讨论】:

  • 非常感谢!您提供了极大的帮助,非常感谢指向其他资源的链接以及将来编写代码的额外提示!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-10
  • 2013-06-15
  • 2016-08-07
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
相关资源
最近更新 更多