1 ;; Exercise 3.26. To search a table as implemented above, one needs to scan through the list of records. This is basically the unordered list representation of section 2.3.3. For large tables, it may be more efficient to structure the table in a different manner. Describe a table implementation where the (key, value) records are organized using a binary tree, assuming that keys can be ordered in some way (e.g., numerically or alphabetically). (Compare exercise 2.66 of chapter 2.)
3 (define (test-case actual expected)
12 (define (make-tree key value)
13 (list key value '() '()))
14 (define (tree-key tree)
16 (define (tree-value tree)
18 (define (left-branch tree)
20 (define (right-branch tree)
22 (define (set-tree-value! tree value)
23 (set-car! (cdr tree) value))
24 (define (insert-left-branch! tree key value)
26 (make-tree key value)))
27 (define (insert-right-branch! tree key value)
28 (set-car! (cdddr tree)
29 (make-tree key value)))
31 ;; (define family-tree (make-tree 'me 'aaron))
32 ;; (insert-left-branch! family-tree 'mom 'amy)
33 ;; (insert-right-branch! family-tree 'dad 'james)
34 ;; (insert-left-branch! (left-branch family-tree) 'grandma '?)
35 ;; (insert-right-branch! (left-branch family-tree) 'grandpa 'sean)
36 ;; (insert-left-branch! (right-branch family-tree) 'grandma '??)
37 ;; (insert-right-branch! (right-branch family-tree) 'grandpa 'yuandu)
38 ;; (test-case (tree-value (right-branch (left-branch family-tree))) 'sean)
39 ;; (test-case (tree-key (left-branch (right-branch family-tree))) 'grandma)
40 ;; (test-case (tree-value (right-branch family-tree)) 'james)
41 ;; (set-tree-value! (right-branch family-tree) 'chen-min)
42 ;; (test-case (tree-value (right-branch family-tree)) 'chen-min)
44 (define (make-table less-thanp)
45 (let ((local-table '()))
46 (define (assoc key tree)
47 (cond ((null? tree) false)
48 ((less-thanp key (tree-key tree)) (assoc key (left-branch tree)))
49 ((less-thanp (tree-key tree) key) (assoc key (right-branch tree)))
50 (else tree))) ;; equality
52 (let ((match (assoc key local-table)))
56 (define (insert! key value)
57 (define (insert-tree! tree)
58 (if (equalp key (tree-key tree))
59 (set-tree-value! tree value)
60 (if (less-thanp key (tree-key tree))
61 (if (null? (left-branch tree))
62 (insert-left-branch! tree key value)
63 (insert-tree! (left-branch tree)))
64 (if (null? (right-branch tree))
65 (insert-right-branch! tree key value)
66 (insert-tree! (right-branch tree))))))
67 (if (null? local-table)
68 (set! local-table (make-tree key value))
69 (insert-tree! local-table)))
71 (cond ((eq? m 'lookup) lookup)
72 ((eq? m 'insert!) insert!)
73 ((eq? m 'debug-print) local-table)
74 (else (error "Unknown request -- MAKE-TABLE" m))))
77 (define (insert! key value table)
78 ((table 'insert!) key value))
79 (define (lookup key table)
80 ((table 'lookup) key))
82 (define israel-sons (make-table = <))
83 (insert! 3 'levi israel-sons)
84 (insert! 5 'dan israel-sons)
85 (test-case (lookup 3 israel-sons) 'levi)
86 (test-case (lookup 5 israel-sons) 'dan)
87 (test-case (lookup 12 israel-sons) false)
88 (test-case (lookup 11 israel-sons) false)
89 (test-case (lookup 1 israel-sons) false)
90 (insert! 12 'benjamin israel-sons)
91 (insert! 11 'joseph israel-sons)
92 (insert! 1 'reuben israel-sons)
93 (test-case (lookup 12 israel-sons) 'benjamin)
94 (test-case (lookup 11 israel-sons) 'joseph)
95 (test-case (lookup 1 israel-sons) 'reuben)
96 (insert! 2 'simeon israel-sons)
97 (test-case (lookup 3 israel-sons) 'levi)
98 (insert! 8 'asher israel-sons)
99 (insert! 7 'gad israel-sons)
100 (insert! 6 'naphtali israel-sons)
101 (insert! 9 'issachar israel-sons)
102 (insert! 10 'zebulun israel-sons)
103 (insert! 4 'judah israel-sons)
104 (test-case (lookup 4 israel-sons) 'judah)
105 (test-case (lookup 8 israel-sons) 'asher)
106 (test-case (lookup 13 israel-sons) false)
107 (insert! 12 'manasseh israel-sons)
108 (insert! 13 'ephraim israel-sons)
109 (insert! 11 'benjamin israel-sons)
110 (test-case (lookup 12 israel-sons) 'manasseh)
111 (test-case (lookup 13 israel-sons) 'ephraim)
112 (test-case (israel-sons 'debug-print)
113 '(3 levi (1 reuben () (2 simeon () ())) (5 dan (4 judah () ()) (12 manasseh (11 benjamin (8 asher (7 gad (6 naphtali () ()) ()) (9 issachar () (10 zebulun () ()))) ()) (13 ephraim () ())))))
115 (define by-mother (make-table string=? string<?))
116 (insert! "leah" 'reuben by-mother)
117 (test-case (lookup "leah" by-mother) 'reuben)
118 (insert! "leah" 'simeon by-mother)
119 (test-case (lookup "leah" by-mother) 'simeon)
120 (insert! "zilpah" 'gad by-mother)
121 (insert! "bilhah" 'dan by-mother)
122 (insert! "rachel" 'joseph by-mother)
123 (test-case (lookup "zilpah" by-mother) 'gad)
124 (test-case (lookup "bilhah" by-mother) 'dan)
125 (test-case (lookup "rachel" by-mother) 'joseph)