sicp每日一题[2.69]
Exercise 2.69
The following procedure takes as its argument a list of symbol-frequency pairs (where no symbol appears in more than one pair) and generates a Huffman encoding tree according to the Huffman algorithm.
(define (generate-huffman-tree pairs)
(successive-merge (make-leaf-set pairs)))
make-leaf-set is the procedure given above that transforms the list of pairs into an ordered set of leaves. successive merge is the procedure you must write, using make-code-tree to successively merge the smallest-weight elements of the set until there is only one element left, which is the desired Huffman tree. (This procedure is slightly tricky, but not really complicated. If you find yourself designing a complex procedure, then you are almost certainly doing something wrong. You can take significant advantage of the fact that we are using an ordered set representation.)
这道题虽然题目说不会很复杂,但是我觉得还是挺难的。首先是要理解 successive-merge 的作用,它是要把一个个叶子按照权重由小到大依次合并成一个树,由于参数已经用 make-leaf-set 进行了排序,所以我们只要从前往后依次把这些“叶子”合并起来就行,每次合并好的树作为一个新的“叶子”与其他叶子一起进行新的合并;这里要注意合并后的树的权重可能会超过排在它之后的叶子,所以要重新对这些“叶子”按权重排序,这里我们可以直接用前面的 adjoin-set 来实现,完整代码如下:
(define (successive-merge leaf-set)
(if (null? leaf-set)
'()
(let ((first (car leaf-set))
(last (cdr leaf-set)))
(if (null? last)
first
(successive-merge (adjoin-set (make-code-tree first (car last))
(cdr last)))))))
(define pairs1 '((A 4) (B 2) (C 1) (D 1)))
(define pairs2 '((A 8) (B 3) (C 1) (D 1) (E 1) (F 1) (G 1) (H 1)))
(generate-huffman-tree pairs1)
(generate-huffman-tree pairs2)
; 结果如下
'((leaf A 4) ((leaf B 2) ((leaf D 1) (leaf C 1) (D C) 2) (B D C) 4) (A B D C) 8)
'((leaf A 8)
((((leaf H 1) (leaf G 1) (H G) 2) ((leaf F 1) (leaf E 1) (F E) 2) (H G F E) 4)
(((leaf D 1) (leaf C 1) (D C) 2) (leaf B 3) (D C B) 5)
(H G F E D C B)
9)
(A H G F E D C B)
17)