Ваш код можно упростить, избегая отрицательных тестов и используя некоторые рефлексивность Пролога.
inOrder(Root, [Left, Root, Right]) :-
inOrder(leftSubtree, Root, Left),
inOrder(rightSubtree, Root, Right).
inOrder(BranchToExplore, Root, Subtree) :-
call(BranchToExplore, Root, Branch)
-> inOrder(Branch, Subtree)
; Subtree = [].
Это восстанавливает структуру дерева, как вложенный троичный список, затем достаточно одного вызова flatten / 2, чтобы, ну, flat , как в вашем оригинале требование.
?- inOrder(8, Tree), flatten(Tree, L).
Tree = [[[[[], -2, []], 1, [[[], 2, []], 3, []]], 5, [[], 6, []]], 8, [[[], 9, [[], 10|...]], 11, [[[], 13|...], 16, [...|...]]]],
L = [-2, 1, 2, 3, 5, 6, 8, 9, 10|...].
Если у вашего Пролога нет call / N, вы можете использовать univ для создания вызываемого термина:
inOrder(BranchToExplore, Root, Subtree) :-
( Callable =.. [BranchToExplore, Root, Branch], call(Callable) )
-> inOrder(Branch, Subtree)
; Subtree = [].
Если мы поменяем местами Left и Root, у нас будет более полезное представление preOrder: preOrder(Root, [Root, Left, Right]) :- ...
.
Наличие структуры дерева в preOrder может быть полезно для дальнейшего процесса: одна «готовая к работе» и полезная реализация в SWI-Prolog - это XML, где деревья представлены как элемент (Tag, Attributes, Subtrees) и могут быть обработано библиотекой (xpath) . Может быть полезным изменить как inOrder / 2, так и inOrder / 3 для восстановления XML.