RKI — Zajęcia 14 — Kodowanie Huffmana

Transkrypt

RKI — Zajęcia 14 — Kodowanie Huffmana
RKI — Zajęcia 14 — Kodowanie Huffmana
Piersa Jarosław
2010-03-09
1
Wprowadzenie
Kodowanie Huffmana jest jednym z najprostszych, co nie oznacza nieskutecznych, algorytmów kompresji.
Wykorzystywany jest w między innymi w formatach JPEG oraz MP3. Sam algorytm jest bezstratny,
to oznacza, że dane po zakodowaniu i odkodowaniu są identyczne z wejściowymi. Kodowanie można
stosować do dowolnych danych, ale w tej lekcji ograniczymy się tylko do tekstów.
Potrzebne wiadomości:
• drzewa binarne,
• listy lub kolejki priorytetowe,
• znajomość typu znakowego,
2
Kodowanie
O kodowaniu można myśleć jak o tłumaczeniu tekstu na obcy język. Zapewne każdy pisał opowiadanie
na język angielski.
Najłatwiejszą metodą jest kodowanie słownikowe. Zakładamy, że mamy dany słownik opisujący jaki
symbol zamienić na jaki, przy czym ten nowy pownien być krótszy niż poprzedni. W tej sytuacji kodowanie sprowadza się do czytania jednego tekstu litery, sprawdzania w słowniku jej kodu i wpisywania go
w drugim tekście. Gdyby wszystkie prace domowe były tak proste.
„ABCD” Napis zajmuje 4 bajty. Zauważmy, że każda litera zajmuje po jednym bajcie (czyli ośmiu
bitach) podczas gdy wystarczą po dwa bity na znak:
• A = „00”
• B = „01”
• C = „10”
• D = „11”
Tak zakodowany napis „00011011”= 0x1B liczy tylko 8 bitów czyli 1 bajt. Wniosek: nie ma sensu
kodować symboli, które w tekście nie występują.
„AABC ABAD BACA ABAA” Spacje są tylko dla czytelności. Tekst ma 16 znaków, ale niektóre z
nich występują częściej niż inne.
litera
ilość wystąpień
A
8
Przy powyższym kodowaniu mamy 32 bity = 4 bajty.
Ale można znaleźć jeszcze sprytniejsze kodowanie:
• A = „0”
• B = „10”
1
B
4
C
2
D
1
1
0
0
A
1
0
B
1
C
D
Rysunek 1: Drzewo słownikowe.
• C = „110”
• D = „111”
Zauważyć można, że im częstsza litera tym krótszy ma kod.
Po zakodowaniu mamy: „0010110 0100111 1001100 01000”. 7+7+7+5 = 26 bitów. Choć nadal trzeba
6
tę wartość zaokrąglić do 4B to licząc względnie zaoszczędziliśmy 32
czyli około 18%.
3
Dekodowanie
Trzymając się porównania do języków obcych, dekodowanie jest tłumaczeniem tekstu z obcego języka na
nasz.
Spróbujmy przetłumaczyć tekst ’110111’ według słownika:
• A = „0”
• B = „1”
• C = „10”
• D = „01”
Tu niestety pojawiaja się problem. fragment „101” można przetłumaczyć na dwa sposoby. Może być
to „BD” albo też „CB”. Nie jest to problem niewłaściwego tekstu, a niewłaściwego słownika. Języku
literką „C” można odczytać jako „BA”.
Rozważmy inne kodowanie:
• A = „0”
• B = „10”
• C = „110”
• D = „111”
oraz tekst ’110111’. Tłumaczy się on na „CD”. Po chwili zastanowienia dodamy, że jest to jedyne
tłumaczenie.
Własnością jaką spełnia dobry słownik jest to, że żaden kod nie jest prefiksem innego. W niepoprawnym słowniku widizmy, że „0” jest prefiksem „01”. Dobry słownik jest reprezentowany poprzez drzewo
binarne, w którym:
• każdy węzeł ma albo dwoje potomków, albo żadnego,
• słowa kluczowe (litery) są w liściach,
• przejście do prawego potomka oznacza dopisanie do koowania „1”, przejście do lewego — „0”.
2
Mając gotowe drzewo tekst odczytujemy:
• czytamy znak,
• schodzimy do właściwej gałęzi,
• w wypadku dojścia do liścia — wypisujemy literę z liścia oraz wracamy do korzenia drzewa.
4
Drzewo Huffmana
Doszliśmy zatem do pytania, jak stworzyć drzewo słownikowe, które do tygo było by optymalne pod
kądem ilości bitów w skompresowanym tekście?
Odpowiedzi udzielił David Huffman w roku 1952.
1. Dla każdego znaku policz ilość jego wystąpień w tekście do kompresji.
2. Usuń z dalszych rozważań znaki, które nie występują tekście.
3. Dla każdego ze znaków zbuduj drzewo binarne:
• Drzewo składa się z jednego węzła, nie ma żadnego potomka,
• Jedyny węzeł posiada zapisaną literę którą reprezentuje,
• Dodatkowo posiada klucz, który jest ilością wystąpień litery w tekście.
4. Ustaw drzewa w kolejce priorytetowej niemalejącej według klucza (tj. im mniejsza ilość wystąpień
tym bliżej początku kolejki). Na przykład można ustawić drzewa w posortowaną listę.
5. Dopuki w kolejce są przynajmniej dwa drzewa powtarzaj:
(a) Zdejmij pierwsze drzewo z kolejki (tj. te które ma najmniejszy klucz). Oznacz ja jako A.
(b) Zdejmij jeszcze jedno pierwsze drzewo z kolejki. Oznacz je jako B.
(c) Stwórz nowe drzewo D takie że:
•
•
•
•
D.klucz = A.klucz + B.klucz
D.prawyP otomek = A
D.lewyP otomek = B
D.litera — nie będzie potrzebne
(d) Wstaw nowoutworzone drzewo D do kolejki/listy tak aby nie zaburzyć porządku na kluczach,
6. Zwróć pozostałe jedyne drzewo w kolejce.
Etapy działania algorytmy na rysunku 2
5
Zadanie 1
Napisz program, który wczyta liczbę znaków n, a następnie tekst długości n znaków. We wczytywanym
tekście nie będzie spacji, znaków interpunkcyjnych ani cyfr, będą wyłącznie litery. Uwaga: małe i wielkie
litery należy traktować jednakowo. Program powienien wyświetlić listę znaków występujących w tekście
oraz liczbę wystąpień. Znaki powinny być posortowane niemalejąco. W przypadku znaków o jednakowej ilości wystąpień decyduje kolejność alfabetyczna (wcześniejsza litera w alfabecie będzie wyświetlona
wcześciej).
Przykładowe dane:
9 abbcaabdc
D
C
A
B
1
2
3
3
3
3
D1
C2
B4
A8
C2
(a) Krok 1
B4
A8
D1
(b) Krok 2
1
B4
A8
A8
3
C2
B4
D1
3
C2
(c) Krok 3
D1
(d) Krok 4
Rysunek 2: Działanie algorytmu.
6
Zadanie 2
Napisz program który wczyta liczbę znaków n, a następnie tekst sługości n znaków. Program powinien
wypisać na ekran tekst skompresowany algorytmem Huffmana.
16
AABCABADBACAABAA
0010110010011110011000100
4

Podobne dokumenty