Учитывая список элементов, вернуть все возможные сбалансированные двоичные деревья, содержащие точно элементы этого списка. В нашем случае допустимое дерево имеет конструкцию: tree(_, left, right)
. Например:
?- avl_tree_planter(X, [yin, yang]).
X = tree(yang, tree(yin, nil, nil), nil) ;
X = tree(yin, tree(yang, nil, nil), nil) ;
X = tree(yin, nil, tree(yang, nil, nil)) ;
X = tree(yang, nil, tree(yin, nil, nil)) ;
Я попытался вывести все возможные варианты, используя обходы inorder, preorder и postorder:
abs_diff(L,R,D) :- D is L-R, L >= R.
abs_diff(L,R,D) :- D is R-L, R >= L.
height(nil,0).
height(tree(_,L,R), H) :-
height(L,HL), height(R,HR),
max_num(HL,HR,MaxH), H is MaxH + 1.
avl_tree_planter(nil,[]).
avl_tree_planter(tree(X,L,R), Xs) :-
height(L,HL), height(R,HR),
abs_diff(HL,HR,Diff), Diff =< 1,
avl_tree_planter(L,Ls), avl_tree_planter(R,Rs),
append(Ls,[X|Rs],Xs). % inorder
avl_tree_planter(tree(X,L,R), Xs) :-
height(L,HL), height(R,HR),
abs_diff(HL,HR,Diff), Diff =< 1,
avl_tree_planter(L,Ls), avl_tree_planter(R,Rs),
append(Rs, [X], Xs1), % postorder
append(Ls, Xs1, Xs).
avl_tree_planter(tree(X,L,R), Xs) :-
height(L,HL), height(R,HR),
abs_diff(HL,HR,Diff), Diff =< 1,
avl_tree_planter(L,Ls), avl_tree_planter(R,Rs),
append([X|Ls], Rs, Xs). % preorder
В некоторых онлайн-интерпретаторах для ввода:
avl_tree_planter(X,[a,b]).
он выводит:
X = tree(a, nil, tree(b, nil, nil))
двенадцать раз, а затем переходит к бесконечному l oop, а в другом он повторяется бесконечно.
Я поставил условие остановки для рекурсия, так что я делаю не так?