Search code examples
prologbinary-search-treepreorder

Trying to print out preOrder Traversal in prolog


I'm implementing a Binary Search Tree in prolog and I'm trying to have printouts for each traversal type, preOrder, inOrder, and postOrder.

My test Tree is: bst(bst(bst(empty,2,empty),4,empty),5,bst(bst(empty,6,empty),8,empty)).

Here's what I have so far:

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

And it works but the user has to press space to get each element.

5
True
4
True
2
True
8
True
6
False

I'd rather it print out in the form 5 4 2 8 6

So I modified the code above to:

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

Now it only prints out 5 4 2 false

I'm pretty new to prolog, can anyone explain why adding the individual predicates to one single predicate is acting differently than 3 separate ones?


Solution

  • Why adding the individual predicates to one single predicate is acting differently than 3 separate ones?

    A predicate with multiple clauses (what you call individual predicates) are evaluated as OR, and a single clause predicate with multiple statements separated by , is evaluated as AND.

    If you change this

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

    which can also be written as

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

    to

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

    then you will get what you seek.


    Since you are new to Prolog I will also give you a review of your code.

    To use your original tree and predicates

    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).
    

    I did this

    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).
    

    the line tree(T) read the tree as a fact and then bound the tree to the variable T so I would not have to type it in each time.

    Then I created a test predicate with the name _01 so I would not clash with other test to come.

    Example run:

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

    Why do you have to press the space bar after each answer?

    (This was done using SWI-Prolog).

    This example shows why.

    test_02 :- write("First").
    test_02 :- write("Second").
    
    ?- test_02.
    First
    true ;
    Second
    true.
    

    Each time the predicate test_02/0 is executed it results in a solution and when a solution is given you have to press the space bar to see the next solution.

    Also notice the ; at the end of the first answer. This is Prolog telling you that a choice point exists and there may be another answer. If it were a . then there would be no more answers.


    For your rewrite which doesn't work

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

    Example run:

    ?-  test_03.
    5 4 2 
    false.
    

    If you run it with the trace you will see that it doesn't reach a choice point.
    See What is redo in Prolog when you trace?


    However if you do this

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

    Example run:

    ?- test_04.
    5 4 2 8 6 
    false.
    

    You will get what you seek. The key difference between preOrder_03 and preOrder_04 is that preOrder_03 has a , at one place and preOrder_04 has a ; at one place. A comma (,) is a logical AND and a semicolon (;) is a logical OR.