I am studying Prolog and I find it difficult to implement a predicate that takes a list and builds a balanced tree from it.
I have implemented these predicates that build an AVL Tree (I have taken it from Bratko book and it works fine):
%%% A program for constructing and searching an avl tree.
%%% Based on Bratko pp 244ff.
%%% Build the tree.
%% The root of the tree is Key.
addavl( nil/0, Key, avl(nil/0, Key, nil/0)/1 ).
addavl( avl(Left, Y, Right)/Hy, Key, NewTree):-
eq(Y, Key),
!,
NewTree = avl(Left, Y, Right)/Hy.
addavl( avl(Left, Y, Right)/Hy, Key, NewTree):-
gt(Y, Key),
addavl(Left, Key, avl(Left1, Z, Left2)/_ ),
combine(Left1, Z, Left2, Y, Right, NewTree).
addavl( avl(Left, Y, Right)/Hy, Key, NewTree):-
gt(Key, Y),
addavl(Right, Key, avl(Right1, Z, Right2)/_ ),
combine(Left, Y, Right1, Z, Right2, NewTree).
combine(T1/H1, A, avl(T21, B, T22)/H2 , C, T3/H3,
avl(avl(T1/H1, A, T21)/Ha, B, avl(T22, C, T3/H3)/Hc)/Hb ):-
H2 > H1,
H2 > H3,
Ha is H1 + 1,
Hc is H3 + 1,
Hb is Ha + 1.
combine(T1/H1, A, T2/H2, C, T3/H3,
avl(T1/H1, A, avl(T2/H2, C, T3/H3)/Hc)/Ha ):-
H1 >= H2,
H1 >= H3,
max1(H2, H3, Hc),
max1(H1, Hc, Ha).
combine(T1/H1, A, T2/H2, C, T3/H3,
avl(avl(T1/H1, A, T2/H2)/Ha, C, T3/H3)/Hc ):-
H3 >= H2,
H3 >= H1,
max1(H1, H2, Ha),
max1(Ha, H3, Hc).
max1(U, V, Max):-
( U > V,
!,
Max is U + 1
; Max is V + 1
).
eq(X, Y):-
X == Y,
!,
write(X),
write(' Item already in tree\n').
So I have the addavl(Tree, Element, NewTree/Height)
predicate that adds the new element to a Tree
generating a new AVL tree.
Now I would like to create a new predicate that uses this addavl/3
predicate to create a new AVL tree from a list of elements.
For example, if I have the list: [1,2,3]
, this new predicate creates a new AVL tree that contains the elements 1,2,3.
I am trying to do this but I am finding some difficulties to do it.
I have implemented something like this (but it doesn't work):
%% BASE CASE: The list is empty, so there is no element to insert
%% into the AVL Tree:
buildTreeList(Tree, [], NewTree, Height) :- !.
%% If I am inserting the first element in the AVL Tree
%% the hight H of the Tree after the insertion is 1:
buildTreeList(Tree, [Head|Tail], NewTree, 1) :-
addavl(nil/0, Head, avl(nil/0, Head, nil/0)/H),
Tree = nil/0,
NewTree = avl(nil/0, Head, nil/0)/1,
buildTreeList(NewTree, Tail, NT, Height).
buildTreeList(Tree, [Head|Tail], NewTree, H) :-
addavl(Tree, Head, avl(Tree, Head, NewTree)/H),
buildTreeList(NewTree, Tail, NT, Height).
My idea is: the addavl/3
predicate adds an element to a new AVL tree and gives me also the height of this new tree (because I have the couple NewTree
/Height
).
So my idea is to:
Scroll through the list of items until the empty list (the base case: there is no items in the list so I don't insert anything into the AVL Tree)
Insert any element of the list into the AVL tree.
If the AVL Tree is empty it has
height=0
so I am creating a new AVL Tree by:addavl(nil/0, Head, avl(nil/0, Head, nil/0)/H)
If the AVL Tree is not empty I insert into it.
But it doesn't work and probably is the wrong way to do this thing.
Could someone help me?