SICP §2.3.4(Haffman 符号化木 その5 [重み付き要素の集合])
う〜ん、このセクション何を言いたいのかいまいち確信が持てない。。
とりあえずコードを写経してコメントを付加していってみよう。
(define (adjoin-set x set) (cond (;母体となるリストが空なら新規生成する。 (null? set) (list x)) (;「挿入したい枝の重み」<「リストの先頭の枝の重み」なら挿入したい枝を先頭に連結。 (< (weight x) (weight (car set))) (cons x set)) (else ;「リストの先頭の葉の重み」≦「挿入したい葉の重み」なら再帰処理。 (cons (car set) (adjoin-set x (cdr set))))))
x、及び set の要素は「葉」または「枝」だ。で、x と set の先頭の枝(または葉)の重みを比較して、x の方が小さければ先頭に挿入する、ということをやっているだけ。
これだけだとまだちょっとよく分からない。
枝で確認するのは大変だから、とりあえず葉だけで実験。
うむ。ちゃんと昇順になっとるね。
gosh> (define leafs '())
leafs
gosh> leafs
()
gosh> (define leafs (adjoin-set (make-leaf 'A 4) leafs))
leafs
gosh> leafs
( (leaf A 4))
gosh> (define leafs (adjoin-set (make-leaf 'B 2) leafs))
leafs
gosh> leafs
( (leaf B 2) (leaf A 4))
gosh> (define leafs (adjoin-set (make-leaf 'C 5) leafs))
leafs
gosh> leafs
( (leaf B 2) (leaf A 4) (leaf C 5))
gosh> (define leafs (adjoin-set (make-leaf 'D 3) leafs))
leafs
gosh> leafs
( (leaf B 2) (leaf D 3) (leaf A 4) (leaf C 5))
gosh>
その次に記載されているサンプルコードが、adjoin-set 手続きを使って何やらやっている。
この手続は、こんなリストを第1引数として受け取るらしい。(あくまでもサンプルね。)
こちらも写経してみよう。
( (A 4) (B 2) (C 1) (D 1))
(define (make-leaf-set pairs) (if (null? pairs) ;入力されたリストが空リストなら空リストを返却。 '() ;何かしら要素が存在した場合は、先頭要素を pair として取り出して、 (let ((pair (car pairs))) ;pair から leaf を生成、それを残りの pairs を使用して生成される枝の母集団に挿入する。 (adjoin-set (make-leaf (car pair) ;記号 (cadr pair)) ;頻度 (make-leaf-set (cdr pairs))))))
これ、ただ単純にサンプルデータを元にして leaf を作りながら、重みの低いものから高いものに整列しているだけか。Huffman木を生成する為の手続じゃないんだなぁ。
一応実験して確認しておこう。
順番を変化させてもちゃんと重みの低いもの→高いものの順序づけられたリストになってるね。
gosh> (make-leaf-set '((A 4) (B 2) (C 1) (D 1)))
( (leaf D 1) (leaf C 1) (leaf B 2) (leaf A 4))
gosh> (make-leaf-set '((B 2) (C 1) (A 4) (D 1)))
( (leaf D 1) (leaf C 1) (leaf B 2) (leaf A 4))
gosh> (make-leaf-set '((C 1) (B 2) (A 4) (D 1)))
( (leaf D 1) (leaf C 1) (leaf B 2) (leaf A 4))
gosh>
なんつーか、このサンプルデータを受け取ったらHuffman木を生成してくれる手続とかはこれ以降の「問題」で出てくるのかな。