SICPを読む(77) 問題2.66 集合と情報検索

さて、二進木の最後の問題。「データベースをつくろう」という問題。

問題 2.66

要約すると、idからデータを検索する二進木データベースの設計をせよ。という問題。

まずはデータ構造の変更

1レコードのデータ構造を変更します。

なるべく変更点が少ない方がいいので、1レコードのデータ構造は

((id . データ)  )

((0 . Scheme) () ())

とします。

データ構造を変えたので、アクセサをチョッといじります。

(define entry caar)
(define data cdar)

変更点はこれだけ。ホントはentryをidに変えたい所なんだけど、色々面倒そうなので・・・。


(id . data)な対を作るコンストラクタを作っておいてっと。

(define (make-entry id data)
  (cons id data))

データ構造設計終わり。

データ入力の簡易化

リストでガガーっと入力したいので、サポートツール作り。

(define (make-list id l)
  (if (null? l)
      '()
      (cons (make-entry id (car l))
            (make-list (+ id 1) (cdr l)))))

(define db-list
   (make-list 0 '(Scheme Commn-lisp C C++ Haskell Logo Ruby JavaScript)))
; ((0 . Scheme) (1 . Commn-lisp) (2 . C) (3 . C++)
;  (4 . Haskell) (5 . Logo) (6 . Ruby) (7 . JavaScript))

これで、list->treeが使えます。

(define db (list->tree db-list))
; ((3 . C++) ((1 . Commn-lisp) ((0 . Scheme) () ()) ((2 . C) () ()))
;            ((5 . Logo) ((4 . Haskell) () ()) ((6 . Ruby) () ((7 . JavaScript) () ()))))

データベース完成!!

検索してみる

element-of-set?をチョチョイといじってっと。

(define (lookup key set)
  (cond ((null? set) #f)
        ((= key (entry set)) (data set))
        ((< key (entry set))
         (lookup key (left-branch set)))
        ((> key (entry set))
         (lookup key (right-branch set)))))

id(key)で検索してみます。

(lookup 0 db) ; Scheme
(lookup 1 db) ; Commn-lisp
(lookup 6 db) ; Ruby

うまくいきました。

疑問

  • 不釣り合いな木の解消はどうすればいいんだろう。
  • idの検索は早いけど、データの検索を早くするにはどうすればいいんだろう。

まだまだ木構造に謎が多い。これからの課題にしておこう〜。