转载自:https://mp.weixin.qq.com/s/I2hjkWOV1e2qaQuE8ASwVg
7、使用给定数量的节点构造高度平衡的二叉树
考虑一个高度为H的高度平衡的二叉树。它可以包含的最大节点数是多少?显然,MaxN = 2 ** H-1。但是,最小数MinN是多少?这个问题比较困难。尝试找到一个递归语句并将其转换为谓词minNodes/2,定义为以下形式:
minNodes(H,N):- N是高度为H的高度平衡二叉树中的最小节点数。
另一方面,我们可能会问:具有N个节点的高度平衡的二叉树可以具有的最大高度H是多少?定义为以下形式:
maxHeight(N,H):-H是具有N个节点的高度平衡二叉树的最大高度
现在,我们可以解决主要问题:使用给定的节点数量构造所有高度平衡的二叉树。
hbal_tree_nodes(N,T):-T是具有N个节点的高度平衡的二叉树。
1 :- ensure_loaded(p4_06).
2
3 minNodes(0,0) :- !.
4 minNodes(1,1) :- !.
5 minNodes(H,N) :-
6 H > 1,
7 H1 is H - 1,
8 H2 is H - 2,
9 minNodes(H1,N1),
10 minNodes(H2,N2),
11 N is 1 + N1 + N2.
12
行注释:
1. 装入hbal_tree/2谓词
2. 空行
3. 高为0节点为0
4. 高为1时节点为1
5. N是高度为H的高度平衡二叉树中的最小节点数
6. 确保树的高度大于1
7. 下一层树
8. 自己思考一下试试,然后想办法验证一下
9. 左树
10. 右树
11. 建议手工推演一下
12. 空行
13 maxNodes(H,N) :-
14 N is 2**H - 1.
15
16 minHeight(0,0) :- !.
17 minHeight(N,H) :-
18 N > 0,
19 N1 is N//2,
20 minHeight(N1,H1),
21 H is H1 + 1.
22
行注释:
13. N是高度为H的高度平衡二叉树中的最大节点数
14. 最大节点数是2的H次幂减1
15.
16. H是具有N个节点的高平衡二叉树的最小高度
17.
18. 确保N大于0
19. 将树分两半
20. 取矮的计算
21. 那么正常高度就为结果值增加1
22.
23 maxHeight(N,H) :-
24 maxHeight(N,H,1,1).
25
26 maxHeight(N,H,H1,N1) :-
27 N1 > N, !,
28 H is H1 - 1.
29 maxHeight(N,H,H1,N1) :-
30 N1 =< N,
31 H2 is H1 + 1,
32 minNodes(H2,N2),
33 maxHeight(N,H,H2,N2).
34
行注释:
23. H是具有N个节点的高度平衡的二叉树的最大高
24. 调用maxHeight/4
25.
26.
27. 当N小于N1时截断
28.
29.
30.
31.
32. 给定高的最少节点,获得最小节点数
33. 由减点数得到高
34.
35 hbal_tree_nodes(N,T) :-
36 minHeight(N,Hmin),
37 maxHeight(N,Hmax),
38 between(Hmin,Hmax,H),
39 hbal_tree(H,T),
40 nodes(T,N).
41
行注释:
35. T是具有N个节点的高平衡的二叉树
36. 由节点数得到最小高
37. 由节点数得到最大高
38. H取值从Hmin起到Hmax值区间内的数
39. 由H得到高平衡的数
40. 过滤掉节点数不是N的数
41. 空行
42 nodes(nil,0).
43 nodes(t(_,Left,Right),N) :-
44 nodes(Left,NLeft),
45 nodes(Right,NRight),
46 N is NLeft + NRight + 1.
47
48 count_hbal_trees(N,C) :-
49 setof(T,hbal_tree_nodes(N,T),Ts),
50 length(Ts,C).
行注释:
42. 二叉树T有N个节点
43.
44. 递归验证左树
45. 递归验证右树
46. 左树节点数+右树节点数+根节点1
47. 空行
48. 有N个节点的C个不同的高度平衡二叉树
49. 根据参数1中的指示T,将参数2中T的所有解放到参数3的列表中
50. 获取列表Ts的长度C
测试:
?- consult('p4_07.pl').
true.
?- hbal_tree_nodes(7,T).
T = t(x, t(x, t(x, nil, nil), t(x, nil, nil)), t(x, t(x, nil, nil), t(x, nil, nil))) .
?- count_hbal_trees(4,C).
[t(x,t(x,nil,nil),t(x,nil,t(x,nil,nil))),t(x,t(x,nil,nil),t(x,t(x,nil,nil),nil)),t(x,t(x,nil,t(x,nil,nil)),t(x,nil,nil)),t(x,t(x,t(x,nil,nil),nil),t(x,nil,nil))]
C = 4.
?-
8、计算二叉树的叶子
叶子是没有后继的节点。谓词count_leaves/2对页节点进行计数。
count_leaves(T,N) :- 二叉树T有N个叶节点
1 count_leaves(nil,0).
2 count_leaves(t(_,nil,nil),1).
3 count_leaves(t(_,L,nil),N) :-
4 L = t(_,_,_),
5 count_leaves(L,N).
6 count_leaves(t(_,nil,R),N) :-
7 R = t<