Search code examples
listprologdcgdcg-semicontext

breadth first on binary tree - using Semicontext notation


I would like to compute list being bfs order on binary tree. Moreover, it should work in second side - for list it find tree.
Can you give me some hint, so far I have used something like that, of course it doesn't work...

bfs(nil) --> [].
bfs(t(X, L, R)), [X] --> bfs(L), bfs(R).

Solution

  • Looks like @repeat came up with a nice DCG solution. I had, in the meantime, come up with a "traditional" queue-based solution that is non-DCG:

    bfs_tree_list(nil, []).
    bfs_tree_list(Tree, List) :-
        bfs_q_list([Tree], List).
    
    bfs_q_list([], []).
    bfs_q_list([t(X,L,R)|Qs], [X|Xs]) :-
        enqueue(L, Qs, Q1),
        enqueue(R, Q1, Q2),
        bfs_q_list(Q2, Xs).
    
    % "naive" enqueue using append
    enqueue(nil, Q, Q).
    enqueue(t(X,L,R), Q1, Q2) :- append(Q1, [t(X,L,R)], Q2).
    

    This follows the methodology shown in the links I provided in my comments. It also follows a strict left-to-right traversal ordering which, I believe, is conventional in binary tree traversals. It's a little simpler than those in the links as those are for more general graphs rather than binary trees. The description of what's happening above is simple:

    1. Start with the top level in the queue
    2. For each element in the queue (until queue is empty)
        (a) Dequeue and accept the current node value
        (b) Enqueue the left and right nodes

    The above code yields:

    | ?- bfs_tree_list(t(3,t(1,nil,t(2,nil,nil)),t(4,nil,nil)), L).
    
    L = [3,1,4,2]
    
    (1 ms) yes
    

    And:

    | ?- bfs_tree_list(Tree, [3,1,4,2]).
    
    Tree = t(3,nil,t(1,nil,t(4,nil,t(2,nil,nil)))) ? a
    
    Tree = t(3,nil,t(1,nil,t(4,t(2,nil,nil),nil)))
    
    Tree = t(3,nil,t(1,t(4,nil,t(2,nil,nil)),nil))
    
    Tree = t(3,nil,t(1,t(4,t(2,nil,nil),nil),nil))
    
    Tree = t(3,nil,t(1,t(4,nil,nil),t(2,nil,nil)))
    
    Tree = t(3,t(1,nil,t(4,nil,t(2,nil,nil))),nil)
    
    Tree = t(3,t(1,nil,t(4,t(2,nil,nil),nil)),nil)
    
    Tree = t(3,t(1,t(4,nil,t(2,nil,nil)),nil),nil)
    
    Tree = t(3,t(1,t(4,t(2,nil,nil),nil),nil),nil)
    
    Tree = t(3,t(1,t(4,nil,nil),t(2,nil,nil)),nil)
    
    Tree = t(3,t(1,nil,nil),t(4,nil,t(2,nil,nil)))
    
    Tree = t(3,t(1,nil,nil),t(4,t(2,nil,nil),nil))
    
    Tree = t(3,t(1,nil,t(2,nil,nil)),t(4,nil,nil))
    
    Tree = t(3,t(1,t(2,nil,nil),nil),t(4,nil,nil))
    
    (1 ms) no
    | ?-
    


    Here's a revised version that uses a difference list rather than append/3.

    bfs_tree_list(nil, []).
    bfs_tree_list(Tree, List) :-
        bfs_q_list([Tree|T], T, List).
    
    bfs_q_list(Q, T, []) :- Q == T, !.
    bfs_q_list([t(X,L,R)|Qs], T, [X|Xs]) :-
        [t(X,L,R)|Qs] \== T,
        enqueue(L, T1, T),
        enqueue(R, NewT, T1),
        bfs_q_list(Qs, NewT, Xs).
    
    enqueue(nil, Q, Q).
    enqueue(t(X,L,R), T, [t(X,L,R)|T]).