我正在研究 Prolog,我发现很难实现一个谓词,它需要一个列表并从中构建一个平衡树。
我已经实现了这些构建AVL 树的谓词(我从 Bratko 书中获取了它,它工作正常):
%%% 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').
所以我有 addavl(Tree, Element, NewTree/Height)
将新元素添加到Tree
生成新 AVL 树的谓词。
现在我想创建一个新的谓词,它使用这个addavl/3
谓词从元素列表中创建一个新的 AVL 树。
例如,如果我有 list: [1,2,3]
,这个新谓词会创建一个包含元素1,2,3的新 AVL 树。
我正在尝试这样做,但我发现这样做有些困难。
我已经实现了这样的东西(但它不起作用):
%% 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).
我的想法是:addavl/3
谓词向新的 AVL 树添加一个元素,并给我这棵新树的高度(因为我有一对NewTree
/Height
)。
所以我的想法是:
滚动项目列表直到出现空列表(基本情况:列表中没有项目,所以我不会在 AVL 树中插入任何内容)
将列表的任何元素插入 AVL 树。
如果 AVL 树是空的,
height=0
那么我将通过以下方式创建一个新的 AVL 树:addavl(nil/0, Head, avl(nil/0, Head, nil/0)/H)
如果 AVL 树不为空,我将插入其中。
但它不起作用,可能是做这件事的错误方法。
有人可以帮助我吗?