-
Notifications
You must be signed in to change notification settings - Fork 10
/
ex-3.26.scm
127 lines (100 loc) · 3.41 KB
/
ex-3.26.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
;;; 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.)
; The table can be described as follows:
;
; * A table is a pair of a value and a set of entries.
; * An entry is a pair of a key and a table.
;
; My answer to Exercise 3.25 is not good. Because it does not abstract how to
; access a set. If the abstraction is properly done, changing a representation
; of a set is fairly simple like examples in section 2.3.3.
;
; Let's revise the answer to Exercise 3.25 by abstracting access to sets:
(define (make-empty-set)
'())
(define empty-set? null?)
(define (make-entry key)
(cons key (make-table)))
(define entry-key car)
(define entry-table cdr)
(define (make-table)
(cons #f (make-empty-set)))
(define table-value car)
(define set-table-value! set-car!)
(define table-set cdr)
(define set-table-set! set-cdr!)
(define (lookup keys table)
(define (go keys table)
(if (null? keys)
(table-value table)
(let ([entry (lookup-set (car keys) (table-set table))])
(if entry
(go (cdr keys) (entry-table entry))
#f))))
(go keys table))
(define (insert! keys value table)
(define (go keys table)
(if (null? keys)
(set-table-value! table value)
(let ([entry (lookup-set (car keys) (table-set table))])
(cond
[entry
(go (cdr keys) (entry-table entry))]
[else
(let ([new-entry (make-entry (car keys))])
(set-table-set! table (adjoin-set! new-entry (table-set table)))
(go (cdr keys) (entry-table new-entry)))]))))
(go keys table)
'ok)
; If a set is represented as an unordered list, lookup-set and adjoin-set! can
; be defined as follows:
(define (lookup-set key set)
(assoc key set))
(define (adjoin-set! entry set)
(cons entry set))
; If a set is represented as a binary tree, lookup-set and adjoin-set! can be
; defined as follows:
(define set-entry car)
(define set-left cadr)
(define set-right caddr)
(define (set-set-left! set x)
(set-car! (cdr set) x))
(define (set-set-right! set x)
(set-car! (cddr set) x))
(define (lookup-set key set)
(if (empty-set? set)
#f
(let* ([entry (set-entry set)]
[ekey (entry-key entry)])
(cond [(< key ekey) (lookup-set key (set-left set))]
[(> key ekey) (lookup-set key (set-right set))]
[else entry]))))
(define (adjoin-set! entry set)
(if (empty-set? set)
(list entry (make-empty-set) (make-empty-set))
(let* ([sentry (set-entry set)]
[skey (entry-key sentry)]
[gkey (entry-key entry)])
(cond [(< gkey skey)
(set-set-left! set (adjoin-set! entry (set-left set)))]
[(> gkey skey)
(set-set-right! set (adjoin-set! entry (set-right set)))])
set)))
; Examples
(define t (make-table))
#?=t
#?=(lookup '(3) t)
#?=(lookup '(2 1 3) t)
#?=(lookup '(9) t)
(insert! '(2) 'A t)
(insert! '(2 1 3) 'ABC t)
(insert! '(9) 'Z t)
#?=t
#?=(lookup '(2) t)
#?=(lookup '(2 1 3) t)
#?=(lookup '(9) t)