二叉树练习 3

转载自: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谓词。提示:考虑节点与其后继

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值