|
| 1 | +#lang racket |
| 2 | +(require compatibility/mlist) |
| 3 | + |
| 4 | +(define (make-bst-table [key-compare <] [key-equal equal?]) |
| 5 | + (let ((root '())) |
| 6 | + ;; the format of a node, from left to right: |
| 7 | + ;; key, value, left-tree, right-tree |
| 8 | + (define (make-node key value) |
| 9 | + (mlist key value '() '())) |
| 10 | + |
| 11 | + (define (node-key node) |
| 12 | + (mcar node)) |
| 13 | + |
| 14 | + (define (node-value node) |
| 15 | + (mcar (mcdr node))) |
| 16 | + |
| 17 | + (define (left-tree node) |
| 18 | + (mcar (mcdr (mcdr node)))) |
| 19 | + |
| 20 | + (define (right-tree node) |
| 21 | + (mcar (mcdr (mcdr (mcdr node))))) |
| 22 | + |
| 23 | + (define (set-left-tree! node left) |
| 24 | + (set-mcar! (mcdr (mcdr node)) left)) |
| 25 | + |
| 26 | + (define (set-right-tree! node right) |
| 27 | + (set-mcar! (mcdr (mcdr (mcdr node))) right)) |
| 28 | + |
| 29 | + (define (lookup given-key) |
| 30 | + (define (iter node) |
| 31 | + (cond ((null? node) #f) |
| 32 | + ((key-equal given-key (node-key node)) |
| 33 | + (node-value node)) |
| 34 | + ((key-compare given-key (node-key node)) |
| 35 | + (iter (left-tree node))) |
| 36 | + (else |
| 37 | + (iter (right-tree node))))) |
| 38 | + (iter root)) |
| 39 | + |
| 40 | + (define (insert! key value) |
| 41 | + (define (iter node) |
| 42 | + (cond ((null? node) |
| 43 | + (make-node key value)) |
| 44 | + ((key-equal key (node-key node)) |
| 45 | + (set-mcar! (mcdr node) value) |
| 46 | + node) |
| 47 | + ((key-compare key (node-key node)) |
| 48 | + (set-left-tree! node (iter (left-tree node))) |
| 49 | + node) |
| 50 | + (else |
| 51 | + (set-right-tree! node (iter (right-tree node))) |
| 52 | + node))) |
| 53 | + (set! root (iter root)) |
| 54 | + 'ok) |
| 55 | + (define (dispatch m) |
| 56 | + (cond ((eq? m 'lookup-proc) lookup) |
| 57 | + ((eq? m 'insert-proc!) insert!) |
| 58 | + (else (error "Unknown operation -- BST-table" m)))) |
| 59 | + dispatch)) |
| 60 | + |
| 61 | +(module+ test |
| 62 | + (require rackunit) |
| 63 | + (test-case "Test for bst-table of number key" |
| 64 | + (define bst-t (make-bst-table)) |
| 65 | + (define get (bst-t 'lookup-proc)) |
| 66 | + (define put (bst-t 'insert-proc!)) |
| 67 | + (check-false (get 10086)) |
| 68 | + (put 5 "five") |
| 69 | + (check-equal? (get 5) "five") |
| 70 | + (put 5 "5") |
| 71 | + (check-equal? (get 5) "5") |
| 72 | + ) |
| 73 | + (test-case "Test for bst-table of symbol key" |
| 74 | + (define bst-t (make-bst-table symbol<? equal?)) |
| 75 | + (define get (bst-t 'lookup-proc)) |
| 76 | + (define put (bst-t 'insert-proc!)) |
| 77 | + (check-false (get 'no-exist-key)) |
| 78 | + (put 'age 18) |
| 79 | + (check-equal? (get 'age) 18) |
| 80 | + (put 'age '20) |
| 81 | + (check-equal? (get 'age) '20) |
| 82 | + ) |
| 83 | + |
| 84 | + (test-case "Test for bst-table of string key" |
| 85 | + (define bst-t (make-bst-table string<? equal?)) |
| 86 | + (define get (bst-t 'lookup-proc)) |
| 87 | + (define put (bst-t 'insert-proc!)) |
| 88 | + (check-false (get "no-exist-key")) |
| 89 | + (put "age" 18) |
| 90 | + (check-equal? (get "age") 18) |
| 91 | + (put "age" 20) |
| 92 | + (check-equal? (get "age") 20) |
| 93 | + ) |
| 94 | + ) |
0 commit comments