0

I have to write a predicate ListInTree(T,X) which is true when T is a tree with a list in each node, and X is the concatenation of all the lists (assuming to visit in Pre-order).

I really can't understand how to use the recursion to visit all the tree.

Thanks

false
  • 10,264
  • 13
  • 101
  • 209
  • Can you show some (7) examples? – User May 06 '15 at 13:04
  • How is a tree is represented in the problem you have to solve?. Try to see what terms are used to represent it and use clauses to deal with each of them, using recursion when any of these terms have subtrees. – migfilg May 06 '15 at 15:14

2 Answers2

2

You do not indicate what tree you are after, so I have to guess. The best in this case is to use a DCG, for grammars are built to model concatenation in the most natural manner possible:

seq([]) -->
   [].
seq([E|Es]) -->
   [E],
   seq(Es).

flattened(empty) -->
   [].
flattened(node(Xs, L, R)) -->
   seq(Xs),
   flattened(L),
   flattened(R).

tree_flattened(T, Es) :-
   phrase(flattened(T), Es).
false
  • 10,264
  • 13
  • 101
  • 209
1

For the sake of example, let us assume the following representation for a tree:

  • The atom nil represents the empty tree.
  • The structure tree/3 represents a non-empty tree tree( Left , Right , Payload ) where Left and Right represent (respectively and recursively) the left and right subtrees, and Payload is the payload for the node: in your case, a list.

Many/Most recursive problems have 1 or 2 "special cases" and the more general case. This is no different:

The special case is that of the empty tree: flattening it produces the empty list.

The general case is that of a non-empty tree: flatting it consists of the following steps:

  • Flatten the left subtree to produce a list
  • Flatten the right subtree to product a list
  • The result is that obtained by the concatenation of

    • the flattened left subtree
    • the current node's payload
    • the flattened right subtree

The Prolog code to accomplish this is pretty much identical to the English description above:

flatten_tree( nil                      , []     ) .  % flattening the empty tree yields an empty list, n'est-ce-pas?
flatten_tree( tree(Left,Right,Payload) , Result ) :- % flattening a non-empty tree consists of
   flatten_tree( Left  , Prefix ) ,                  % - flattening the left subtree,
   flatten_tree( Right , Suffix ) ,                  % - flattening the right subtree,
   concatenate( Prefix , Payload , Suffix , Result ) % - concatenating the three parts
   .                                                 % - easy!

concat( Xs, Ys , Zs , Rs ) :-
  append(Xs,Ys,T1) ,
  append(T1,Zs,Rs)
  .

One might note that another approach might be to use findall/3 and append/2 (if you're using SWI prolog).

First you need a predicate to visit the tree via backtracking:

visit( tree(L,_,_) , P ) :- visit( L , P ) . % visit the left subtree
visit( tree(_,_,P) , P ) .                   % visit the current node
visit( tree(_,R,_) , P ) :- visit( R , P ) . % visit the right subtree

Feel free to rearrange the order of the clauses to get the ordering you'd like. Once you have that, flattening the tree is trivial:

flatten_tree( Tree , List ) :-
  findall( X, visit(Tree,X) , Xs ) ,
  append(Xs,List)
  .
Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135