Program Structure 笔记13 (层次性结构的表示:树的遍历)
(作者:colinboy Email:cybbh@163.com) 2008.5.27
(内容难免出现错误或一些专业词汇使用不当,只是个人笔记,能理解总体内容就好)
上节中讲了2种类型的tree,特点如表所示:
| 2 Children | n Children |
ADT | Binary Tree | Tree |
List Structure | car/cdr recusion | Deep List |
;使用car/cdr实现的deeplist树的map函数
(define (deep-map fn dtree)
(cond ((null? dtree) '())
((pair? dtree)
(cons (deep-map fn (car dtree))
(deep-map fn (cdr dtree))))
(else (fn dtree))))
;测试
(define t1 '((my name) (cao yuan) (li hong) (wang liang)))
(deep-map (lambda (x) (word 'k x)) t1) --> ((kmy kname) (kcao kyuan) (kli khong) (kwang kliang))
树的遍历顺序:
深度优先(depth first order)
深度优先的顺序是对于每个节点,先遍历左边的节点,再遍历右边的,遍历出的输出结果为:
1 2 3 4 5 6 7 8
广度优先(breadth first order)
广度优先是按树的层次遍历数据,也就是一层一层的输出,遍历出的输出结果为:
1 2 5 3 4 6 7 8
深度优先遍历的实现:
(define (depth-first-search tree)
(print (datum tree))
(for-each depth-first-search (children tree)))
广度优先遍历的实现:
(define (breadth-first-search tree)
(bfs-iter (list tree)))
(define (bfs-iter queue)
(if (null? queue) 'done
(let ((task (car queue)))
(print (datum task))
(bfs-iter (append (cdr queue) (children task))))))
深度优先遍历的实现很简单, 广度优先遍历的实现看起来有点难理解,需要仔细分析.
二叉树的深度优先遍历:
对于二叉树的深度优先遍历,有三种常见顺序:
preorder (L,datum,R) 先访问左边元素,再访问节点,最后访问右边
3 + 4 * 5
inorder (datum,L,R) 先访问节点,再访问左边,最后访问右边
+ 3 * 4 5
postorder (L,R,datum) 先访问左边元素,再访问右边,最后访问节点
3 4 5 * +
三种顺序的实现
(define (pre-order tree)
(cond ((null? tree) '())
(else
(print (entry tree))
(pre-order (left-branch tree))
(pre-order (right-branch tree)))))
(define (in-order tree)
(cond ((null? tree) '())
(else
(in-order (left-branch tree))
(print (entry tree))
(in-order (right-branch tree)))))
(define (post-order tree)
(cond ((null? tree) '())
(else
(post-order (left-branch tree))
(post-order (right-branch tree))
(print (entry tree)))))