Reputation: 455
I'm trying to get a program to return the levels of a BT in the way of a list and I'm stuck at this:
nivel(nodo(L,Root,R)) :- nivel(nodo(L,Root,R),X),writeln(X).
nivel(vacio,[]).
nivel(nodo(L,Root,R),[Root|T]) :- nivel(L,T),nivel(R,T),writeln(T).
An example input-output of what I'm trying is:
nivel(nodo(nodo(vacio,4,vacio), t, nodo(vacio,r,vacio))
X =[t]
X =[4,r]
problem is I don't know how to make the program get the new Roots. Any ideas? Also, thanks in advance!
Upvotes: 1
Views: 1121
Reputation:
Quite a tricky one for Prolog, but here's one solution to consider which provides a true level-order (L-R breadth-first) tree traversal:
nivel(nodo(L,Root,R), Level) :-
depth_value_pairs(nodo(L,Root,R), 0, DVPairs),
keylistmerge(DVPairs, Groups),
maplist(keyvalue, Groups, _, Values),
member(Level, Values).
nivel/2
is your entry predicate. Basically, it uses depth_value_pairs/3
, which generates solutions of the form Depth-Value
(e.g., 0-t
to represent the root node t
at ply depth 0
, or 1-4
to represent the node 4
at ply depth 1
, etc.). Then, it uses keylistmerge/2
to merge the list all depth-value pairs into depth groups, e.g., [0-[t], 1-[4,t], ...]
. Then, the maplist(keyvalue...
call busts the Depth-
parts from the lists, and the final predicate call member/2
selects each list to bind to the output Level
.
Here are the other predicate definitions:
depth_value_pairs(vacio, _, []).
depth_value_pairs(nodo(L, Root, R), Depth, [Depth-Root|Level]) :-
NextLevel is Depth + 1,
depth_value_pairs(L, NextLevel, LL),
depth_value_pairs(R, NextLevel, RL),
append(LL, RL, Level).
keyvalue(K-V, K, V).
keylistmerge(KVL, MKVL) :-
keysort(KVL, [K-V|KVs]),
keylistmerge([K-V|KVs], K, [], MKVL).
keylistmerge([], K, Acc, [K-Acc]).
keylistmerge([K0-V|KVs], K, Acc, MKVL) :-
K == K0, !,
append(Acc, [V], NewAcc),
keylistmerge(KVs, K, NewAcc, MKVL).
keylistmerge([K0-V|KVs], K, Acc, [K-Acc|MKVs]) :-
keylistmerge(KVs, K0, [V], MKVs).
Exercising this gives us:
?- nivel(nodo(nodo(vacio,4,nodo(vacio,5,vacio)), t, nodo(vacio,r,vacio)), Level).
Level = [t] ;
Level = [4, r] ;
Level = [5] ;
false.
Note that we rely on the built-in keysort/2
to be order-preserving (stable) so as to preserve the L-R order of nodes in the binary tree.
Upvotes: 1
Reputation: 22585
Here goes a solution, it traverses the tree once an builds a list of the items in each level.
nivel(Arbol, SubNivel):-
nivel(Arbol, [], [], Items),
member(SubNivel, Items),
SubNivel \= [].
nivel(vacio, Items, SubNiveles, [Items|SubNiveles]).
nivel(nodo(Izq, Item, Der), Items, [], [[Item|Items]|NSubNiveles]):-
nivel(Izq, [], [], [MSubItems|MSubNiveles]),
nivel(Der, MSubItems, MSubNiveles, NSubNiveles).
nivel(nodo(Izq, Item, Der), Items, [SubItems|SubNiveles], [[Item|Items]|NSubNiveles]):-
nivel(Izq, SubItems, SubNiveles, [MSubItems|MSubNiveles]),
nivel(Der, MSubItems, MSubNiveles, NSubNiveles).
The second clause of nivel/4 is a hack due to the fact that the algorithm does not know in advance the height of the tree.
Test case:
?- nivel(nodo(nodo(nodo(nodo(vacio,f,vacio),e,nodo(vacio,g,vacio)),b,vacio),a,nodo(vacio,c,nodo(vacio,d,vacio))), X).
X = [a] ; --> Root
X = [c, b] ; --> First Level
X = [d, e] ; --> Second Level
X = [g, f] ; --> Third Level
Upvotes: 1