转载自:https://mp.weixin.qq.com/s/e6Mw5v3So-wgUPDsOixulQ
13、布局二叉树(1)
给定二叉树作为通常的Prolog项t(X,L,R)(或nil)。作为绘制树的准备工作,需要一种布局算法来确定每个节点在矩形网格中的位置。可以考虑几种布局方法,下图显示了其中一种。
在此布局策略中,节点v的位置 通过以下两个规则获得:
x(v)等于节点v在有序序列中的位置
y(v)等于树中节点v的深度
为了存储节点的位置,我们将代表一个节点(及其后继节点)的Prolog项扩展如下:
nil代表空树(通常)
t(W,X,Y,L,R)代表(非空)二叉树,其根W“位于”(X,Y),子树L和R
谓词形如:layout_binary_tree/2:
layout_binary_tree(T,PT) :- PT是从二叉树T获得的“定位”二叉树。
1 :- ensure_loaded(p4_04).
2
3 layout_binary_tree(T,PT) :-
4 layout_binary_tree(T,PT,1,_,1).
5
layout_binary_tree(T,PT,In,Out,D) :- T和PT如 layout_binary_tree/2;
In是有序序列中树T(or PT)开始的位置 ,
Out is the position after the last node of in the
Out是按顺序排列的T (or PT) 最后一个节点之后的位置。
D是T (or PT) 根的深度 .
6 layout_binary_tree(nil,nil,I,I,_).
7 layout_binary_tree(t(W,L,R),t(W,X,Y,PL,PR),Iin,Iout,Y) :-
8 Y1 is Y + 1,
9 layout_binary_tree(L,PL,Iin,X,Y1),
10 X1 is X + 1,
11 layout_binary_tree(R,PR,X1,Iout,Y1).
12
行注释:
1. 确保装入谓词construct/2,用以测试
2. 空行
3. T为起始树,PT是用于’操纵’的当前树
4. 参数3,4为’1’代表从根开始
5. 空行
6. 终结点,即终止条件
7.
8. Y增1赋值给Y1
9. 继续递归左树
10. X增1赋值给X1
11. 继续递归右树
12. 空行
测试:
?- consult('p4_13.pl').
true.
?- construct([n,k,m,c,a,h,g,e,u,p,s,q],T),layout_binary_tree(T,PT).
T = t(n, t(k, t(c, t(a, nil, nil), t(h, t(g, t(e, nil, nil), nil), nil)), t(m, nil, nil)), t(u, t(p, nil, t(s, t(q, nil, nil), nil)), nil)),
PT = t(n, 8, 1, t(k, 6, 2, t(c, 2, 3, t(a, 1, 4, nil, nil), t(h, 5, 4, t(g, 4, 5, t(e, 3, 6, nil, nil), nil), nil)), t(m, 7, 3, nil, nil)), t(u, 12, 2, t(p, 9, 3, nil, t(s, 11, 4, t(q, 10, 5, nil, nil), nil)), nil)) .
14、布局二叉树(2)
上图显示了一种替代的布局方法。找出规则并编写相应的Prolog谓词。提示:在给定级别上,相邻节点之间的水平距离是恒定的。
节点v的位置通过以下规则获得:
(1)y(v)等于树中节点v的深度
(2)如果D表示树的深度(即填充级别的数量),则级别i(从根开始,从1开始)的节点之间的水平距离等于2**(D-i+1)。树的最左侧节点在位置1。
layout_binary_tree2(T,PT) :- PT是从二叉树T获得的“定位”二叉树。
1 :- ensure_loaded(p4_04).
2
3 layout_binary_tree2(nil,nil) :-
4 !.
5
行注释:
1. 确保装入谓词construct/2,用以测试
2. 空行
3. 终止节点
4. 截断
5. 空行
6 layout_binary_tree2(T,PT) :-
7 hor_dist(T,D4),
8 D is D4//4,
9 x_pos(T,X,D),
10 layout_binary_tree2(T,PT,X,1,D).
11
行注释:
6. T为起始树,PT是用于’操纵’的当前树
7. 获取水平距离D4
8. 本节点水平距离
9. 根据D获取位置X
10. 开始调用layout_binary_tree2/5
11.
hor_dist(T,D4) :- D4是T的根节点与其后继节点(如果有)之间水平距离的四倍
12 hor_dist(nil,1).
13 hor_dist(t(_,L,R),D4) :-
14 hor_dist(L,D4L),
15 hor_dist(R,D4R),
16 D4 is 2 * max(D4L,D4R).
17
行注释:
12. 终结点
13. 获取D4
14. 左树到本节点的距离D4L
15. 右树到本节点的距离D4L
16. 取左右两树节点分别到本树节点距离的最大值乘以2赋值给D4作为两节点间的水平距离
17. 空行
x_pos(T,X,D) :- X是T根节点相对于图片坐标系的水平位置。 D是T的根节点与其后继节点(如果有)之间的水平距离。
18 x_pos(t(_,nil,_),1,_) :-
19 !.
20 x_pos(t(_,L,_),X,D) :-
21 D2 is D//2,
22 x_pos(L,XL,D2),
23 X is XL+D.
24
行注释:
18. 终止条件
19. 截断
20. 由距离D获取位置X
21. 下层树两节点的距离为D2
22. 递归去获得XL
23. 的到的位置就是XL加上D2后赋值给X
24.
layout_binary_tree2(T,PT,X,Y,D) :-T和PT与layout_binary_tree/2中的一样;
D是T的根节点与其后继节点(如果有)之间的水平距离。 X,Y是根节点的坐标。
25 layout_binary_tree2(nil,nil,_,_,_).
26 layout_binary_tree2(t(W,L,R),t(W,X,Y,PL,PR),X,Y,D) :-
27 Y1 is Y + 1,
28 Xleft is X - D,
29 D2 is D//2,
30 layout_binary_tree2(L,PL,Xleft,Y1,D2),
31 Xright is X + D,
32 layout_binary_tree2(R,PR,Xright,Y1,D2).
33
行注释:
25. 终止位条件
26. 从根开始
27. Y增1赋值给Y1进到树的下一层
28. 左树的水平位置Xleft
29. 进到下一层水平位置关系
30. 递归左树处理后续
31.进到下一层水平位置关系
32. 递归右树处理后续
33.
测试:
?- consult('p4_14.pl').
true.
?- construct([n,k,m,c,a,e,d,g,u,p,q],T),layout_binary_tree2(T,PT).
T = t(n, t(k, t(c, t(a, nil, nil), t(e, t(d, nil, nil), t(g, nil, nil))), t(m, nil, nil)), t(u, t(p, nil, t(q, nil, nil)), nil)),
PT = t(n, 15, 1, t(k, 7, 2, t(c, 3, 3, t(a, 1, 4, nil, nil), t(e, 5, 4, t(d, 4, 5, nil, nil), t(g, 6, 5, nil, nil))), t(m, 11, 3, nil, nil)), t(u, 23, 2, t(p, 19, 3, nil, t(q, 21, 4, nil, nil)), nil)) .
?-
15、布局二叉树(3)
上图显示了另一种布局策略。该方法产生非常紧凑的布局,同时在每个节点中保持一定的对称性。找出规则并编写相应的Prolog谓词。提示:考虑节点与其后继