速い:
まず、正規のハフマンコードを作成したことを確認します。ここで、短いコードは長いコードの前に数値的に表示されます。これは、最初にハフマンコードを各シンボルのビット数として簡単に記述することで簡単に実行できます。次に、ハフマンコードをシンボル順に最短のコードに割り当て、次にシンボル順に最短のコードを割り当てます。例えば
Symbol Bits
A 2
B 4
C 3
D 3
E 2
F 3
G 4
ビットで並べ替え、シンボルで並べ替えを保持:
Symbol Bits
A 2
E 2
C 3
D 3
F 3
B 4
G 4
ゼロから始まるハフマンコードを割り当てます。
Symbol Bits Code
A 2 00
E 2 01
C 3 100
D 3 101
F 3 110
B 4 1110
G 4 1111
この標準的なアプローチは、実際のコードやツリーを送信する必要がなく、各シンボルのコード長だけを送信する必要があるため、コンプレッサーからデコンプレッサーにハフマンコードを送信するコンパクトな手段を提供します。次に、もう一方の端で上記のようにコードをビルドできます。
次に、デコードテーブル、シンボルテーブル、、Symbol[] = "AECDFBG"
およびコードインデックステーブルを作成します。
Bits Start Index
2 0000 (0) 0
3 1000 (8) 2
4 1110 (14) 5
ここでデコードするために、2ビットから4ビットまでループして、コードが次のビットサイズの開始コードよりも小さいかどうかを確認できます。ストリームから4ビットを引き出して呼び出しますnyb
(ストリームにさらに4ビットがない場合は、ゼロビットを追加して入力します)。if
ループの代わりに'sを使用する擬似コードでは、>>
ビットを下にシフトすることを意味します。
if nyb < Start[Bits are 3] (= 8) then
output Symbol[Index[Bits are 2] (= 0) + (nyb - Start[Bits are 2] (= 0)) >> 2]
remove top two bits from bitstream
else if nyb < Start[Bits are 4] (= 14) then
output Symbol[Index[Bits are 3] (= 2) + (nyb - Start[Bits are 3] (= 8)) >> 1]
remove top three bits from bitstream
else (must be four bits)
output Symbol[Index[Bits are 4] (= 5) + (nyb - Start[Bits are 4] (= 14))]
remove top four bits from bitstream
それをループに変換する方法を理解するのは非常に簡単で、最短のコード長から2番目に長いコード長になります。それが見つからない場合は、最長のコード長である必要があります。
もっと早く:
長さが2**(最長のコードの長さ)のルックアップテーブルを作成します。テーブルの各エントリには、コードのビット数と結果のシンボルが含まれています。ビットストリームのその数のビットをインデックスとして使用します。繰り返しますが、ビットストリームにそれほど多くのビットが残っていない場合は、ゼロを入力します。次に、そのインデックス付きエントリからシンボルを出力し、そのインデックス付きエントリのビット数をビットストリームから削除します(これは、インデックス用にプルしたビット数よりも少ない場合があります。未使用のビットは必ず残してください。ビットストリーム)。繰り返します。ここで、残りのビットストリームから最初の未使用ビットを引き出します。
次のレベルの洗練度では、zlibが行うことを実行できます。最長のコードが比較的長い場合(zlibでは最大15ビットになる可能性があります)、次のアプローチと比較して、テーブルの作成にかかる時間は、デコードで節約された時間に対して支払われない場合があります。2レベルのテーブルがあり、最初のレベルのテーブルは最長のコードよりも短いn
ビットまでカバーします。(zlibでは、15ビットコードn
が最適な選択であることがわかります。)次に、コードがビット以下の場合、テーブルエントリはシンボルとビット数を提供し、上記のように進みます。コードがビットを超える場合は、そのためのサブテーブルに移動しますn == 9
n
n
n
-上記のように、残りのビットを処理するビット値。そのテーブルエントリは、サブテーブルに対してプルするビット数を示し、そのサブテーブルのサイズを定義します。これを呼び出しますk
。ストリームから上位ビットを削除しn
、次のビットをプルして、k
それをサブテーブルへのインデックスとして使用します。次に、コード内のシンボルと残りのビット数を取得し、シングルレベルテーブルのように続行します。n+k
サブテーブルは短いコードしかカバーしない可能性があるため、必ずしも各サブテーブルの最長コードの長さであるとは限らないことに注意してください。最後の1つまたはいくつかのサブテーブルのみがn+k
、最長のコードの長さに等しくなります。
ハフマンコードの構築により、コードが短くなる可能性がはるかに高くなるため、これは非常に高速になる可能性があります。ほとんどの場合、最初のレベルでシンボルを取得しますが、たまに2番目のレベルに移動する必要があります。メインテーブルとすべてのサブテーブルに入力するテーブルエントリの総数は、コードの長さ全体をカバーする大きなテーブルのエントリの数よりもはるかに少なくなる可能性があります。これにより、デコードの準備にかかる時間が短縮されます。
さらに長いハフマンコード(32ビットなど)がある場合は、より多くのレベルのサブテーブルを作成できます。サブテーブルの最適なブレークポイントを決定するには、ある程度の実験が必要です。これは、新しいコードが送信され、テーブルを作成する必要がある頻度によって異なります。