-
Notifications
You must be signed in to change notification settings - Fork 10
/
ex-2.63.scm
144 lines (127 loc) · 4.65 KB
/
ex-2.63.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
(load "./sec-2.3.3-sets-as-binary-trees.scm")
;;; Exercise 2.63.
;;;
;;; Each of the following two procedures converts a binary tree to a list.
(define (tree->list-1 tree)
(if (null? tree)
'()
(append (tree->list-1 (left-branch tree))
(cons (entry tree)
(tree->list-1 (right-branch tree))))))
(define (tree->list-2 tree)
(define (copy-to-list tree result-list)
(if (null? tree)
result-list
(copy-to-list (left-branch tree)
(cons (entry tree)
(copy-to-list (right-branch tree)
result-list)))))
(copy-to-list tree '()))
;;; a. Do the two procedures produce the same result for every tree?
;;; If not, how do the results differ?
; tree->list-1 converts a given binary tree with the following steps:
;
; (1) Flatten the left branch,
; (2) Flatten the right branch,
; (3) Prepend the entry to the flattened right branch,
; (4) Then concatenate (1) and (3).
;
; tree->list-2 converts a given binary tree with the following steps:
;
; (1) Visit each node from right to left,
; (2) Accumulate visited nodes.
;
; Both procedures convert a binary tree with different strategies, but both
; accumulate nodes from right to left. So that both produce the same result
; for every tree.
;;; What lists do the two procedures produce for the trees in figure 2.16?
;;; 7 3 5
;;; / \ / \ / \
;;; 3 9 1 7 3 9
;;; / \ \ / \ / / \
;;; 1 5 11 5 9 1 7 11
;;; \
;;; 11
;;;
;;; Figure 2.16: Various binary trees that represent the set {1,3,5,7,9,11}.
(define figure-2.16-a
(make-tree 7
(make-tree 3
(make-tree 1 '() '())
(make-tree 5 '() '()))
(make-tree 9
'()
(make-tree 11 '() '()))))
(define figure-2.16-b
(make-tree 3
(make-tree 1 '() '())
(make-tree 7
(make-tree 5 '() '())
(make-tree 9
'()
(make-tree 11 '() '())))))
(define figure-2.16-c
(make-tree 5
(make-tree 3
(make-tree 1 '() '())
'())
(make-tree 9
(make-tree 7 '() '())
(make-tree 11 '() '()))))
(define-syntax check
(syntax-rules ()
[(check expr)
(print 'expr " ==> " expr)]))
(check figure-2.16-a)
; figure-2.16-a ==> (7 (3 (1 () ()) (5 () ())) (9 () (11 () ())))
(check figure-2.16-b)
; figure-2.16-b ==> (3 (1 () ()) (7 (5 () ()) (9 () (11 () ()))))
(check figure-2.16-c)
; figure-2.16-c ==> (5 (3 (1 () ()) ()) (9 (7 () ()) (11 () ())))
(check (tree->list-1 figure-2.16-a))
; (tree->list-1 figure-2.16-a) ==> (1 3 5 7 9 11)
(check (tree->list-1 figure-2.16-b))
; (tree->list-1 figure-2.16-b) ==> (1 3 5 7 9 11)
(check (tree->list-1 figure-2.16-c))
; (tree->list-1 figure-2.16-c) ==> (1 3 5 7 9 11)
(check (tree->list-2 figure-2.16-a))
; (tree->list-2 figure-2.16-a) ==> (1 3 5 7 9 11)
(check (tree->list-2 figure-2.16-b))
; (tree->list-2 figure-2.16-b) ==> (1 3 5 7 9 11)
(check (tree->list-2 figure-2.16-c))
; (tree->list-2 figure-2.16-c) ==> (1 3 5 7 9 11)
; (define figure-2.17
; (make-tree 1 '()
; (make-tree 2 '()
; (make-tree 3 '()
; (make-tree 4 '()
; (make-tree 5 '()
; (make-tree 6 '()
; (make-tree 7 '() '()))))))))
; (check (tree->list-1 figure-2.17))
; (check (tree->list-2 figure-2.17))
;;; b. Do the two procedures have the same order of growth in the number of
;;; steps required to convert a balanced tree with n elements to a list? If
;;; not, which one grows more slowly?
; No. tree->list-1 is slower than tree->list-2.
;
; tree->list-1 uses APPEND to concatenate flattend branches, and (append list1
; list2) makes a resulting list by prepending each item in list1 to list2 by
; CONS. So that APPEND is O(n). Suppose that a balanced binary tree with
; N nodes is given to tree->list-1.
;
; * Each node has a left branch,
; * Each i-th depth node has a left branch with N/(2^i) nodes.
; (note that i=1 for the root node)
; * The number of i-th nodes is estimated to 2^(i-1).
;
; So that the number of CONS operations to tree->list-1 is:
;
; sum_{i=1}^{log_2 N} 2^(i-1) * N/(2^i)
; = sum_{i=1}^{log_2 N} N/2
; = (log_2 N) * N/2
;
; Therefore, tree->list-1 is O(N log N).
;
; While tree->list-2 uses only CONS each node from right to left.
; So that it is just O(N).