У меня есть решение, но оно не особенно эффективно. Я реализовал дерево в виде набора из трех списков элементов, таких как [Элемент, Левый, Правый], но оно должно работать так же.
% returns a list of nodes at the given level of the tree
level( [], _, [] ).
level( [Element, _, _], 0, [Element] ) :- !.
level( [_, Left, Right], N, Result ) :-
NewN is N - 1,
level( Left, NewN, LeftResult ),
level( Right, NewN, RightResult ),
append( LeftResult, RightResult, Result ).
% does a bfs, returning a list of lists, where each inner list
% is the nodes at a given level
bfs( Tree, Result ) :-
level( Tree, 0, FirstLevel ), !,
bfs( Tree, 1, FirstLevel, [], BFSReverse ),
reverse( BFSReverse, Result ).
bfs( _, _, [], Accum, Accum ) :- !.
bfs( Tree, Num, LastLevel, Accum, Result ) :-
level( Tree, Num, CurrentLevel ), !,
NewNum is Num + 1,
bfs( Tree, NewNum, CurrentLevel, [LastLevel|Accum], Result ).
Должно быть возможно сделать это в O (n), но это O (n ^ 2). Я начал работать над другим решением, которое возвращает уровень каждого элемента в O (n), но я не уверен, как преобразовать этот список в формат решения в O (n), не прибегая к assert / retract.