わかりましたので、文字を含むペアのリストとその頻度、またはテキストで見られた回数が与えられたとします。ex '((#\a . 4) (#\b . 2) (#\c . 9)) 2つの最低周波数を見つけて、それらをツリーに結合できるようにするにはどうすればよいですか? これらを見つけるのに役立つ何らかの機能はありますか?
2 に答える
頻度のソートされていないリスト表現のみを使用することは、おそらくこの問題に対する正しいアプローチではありません。その理由は次のとおりです。最小値を繰り返し見つけることが、ハフマン エンコーディング ツリーを計算するための主な操作です。この最小検索操作を繰り返すときに、リスト全体を検索し続ける必要はありません。
問題への最初の攻撃として、ソートを、最小値の検出を高速化するためのアプローチと考えてください。
ただし、この特定の問題については、コレクションを表すデータ構造であるバイナリヒープの使用を検討する必要があります。ヒープから最小要素を引き出すのが非常に安価であるという、非常に優れた特性があります。ハフマン ツリーの構築プロセス中に、新しい要素をコレクションに追加することになります。リストを何度も再利用したくありません。
Racket には、標準ライブラリのデータ/ヒープコレクションにバイナリ ヒープの実装があります。これをハフマン ツリーの構築に適用するのは非常に簡単です。以下は、ヒープを使用した基本的なアルゴリズムを実装しています。
(require data/heap)
;; ...
;; make-huffman-tree: (listof leaf) -> node
(define (make-huffman-tree leaves)
(define a-heap (make-heap node<=?))
(heap-add-all! a-heap leaves)
(for ([i (in-range (sub1 (length leaves)))])
(define min-1 (heap-min a-heap))
(heap-remove-min! a-heap)
(define min-2 (heap-min a-heap))
(heap-remove-min! a-heap)
(heap-add! a-heap (merge (+ (frequency min-1) (frequency min-2))
min-1 min-2)))
(heap-min a-heap))
ここで、自由変数node<=?
は、頻度によって比較する方法を知ることを目的としており、merge
2 つのことを取りまとめることを目的としています。
ハフマン ツリー構成の核心は図 2 で見ることができますmake-huffman-tree
。ヒープを使用して 2 つの最小要素を引き出し、それらをマージして、結果をヒープに戻します。木が1本になるまで繰り返します。