26: Huffmanovo kodiranje

Avtor

Avtor: Boštjan Jaklič (bostjan.jaklic@siol.net)
Visokošolski strokovni študij Praktična matematika
Študijsko leto 2004/05
 

Viri:

[1] fotokopije iz treh knjig - študijski material

[2] David A. Huffman, A method for the Construction of Minimum-Redundancy Codes, Proceedings of the I.R.E., September 1952; http://compression.graphicon.ru/download/articles/huff/huffman_1952_minimum-redundancy-codes.pdf

[3] Debra A. Lelewer, Daniel S. Hirschberg, Data compression, internetna referenca http://www.ics.uci.edu/~dan/pubs/DataCompression.html

[4] Mark Nelson & Visicron Corp, Huffman Coding, internetni seznam povezav/referenc za Huffmanovo kodiranje http://datacompression.info/Huffman.shtml

[5] Kenneth D. Huffman, Huffman Coding, 1997-2005, http://www.huffmancoding.com/david/algorithm.html

[6] William A. McKee, Huffmanovo kodiranje v C++

 

Kratek opis problema

Tekstovne datoteke lahko stisnemo tako, da zamenjamo pogosto ponavljajoče se besede s krajšimi simboli. Eden izmed načinov takega kodiranja je Huffmanovo kodiranje. Huffmanovo kodiranje je dobilo ime po Davidu Huffmanu, ki je leta 1952 objavil članek [2], v katerem je opisal metodo.

Algoritem

Huffmanovo kodiranje je pogosto uporabljen in učinkovit način stiskanja podatkov. Stiskanje je rezultat zamenjave točno določenega števila bitov za posamezen znak (npr. ASCI - 7 bitov, Unicode - 16 bitov) v kodo s spremenljivo dolžnino, kjer pogosteje zastopani znaki dobijo čim krajšo dvojiško kodo.

Ključna podatka za kodiranje sta torej nabor znakov in pogostost pojavljanja posameznega znaka v besedilu. Zato moramo besedilo oziroma podatke najprej analizirati, z drugim prehodom čez besedilo/podatke pa zgradimo drevo, ki predstavlja optimalno kodiranje s predpono.

Huffmanovo kodiranje ne povzroči izgube ali spremembe podatkov po stiskanju, zato velja za zanesljivo metodo. Je pa res, da moramo pri kodiranju shraniti tudi Huffmanovo drevo, kjer je zapisana dvojiška koda, s pomočjo katere stisnjene podatke lahko povrnemo v prvotno obliko.

Implementacija algoritma

Koda se nahaja tukaj in je zapisana v eni sami datoteki.

Pri implementaciji algoritma sem zgradil naslednje pomožne razrede/strukture:

Razred Znak sem uporabil za opis znaka:

Vozlisce je s povezavama na sinova razsirjen Znak in predstavlja vozlisce v drevesu:

Drevo je povezan seznam Vozlisc in tvori dvojiško drevo:

Za gradnjo Huffmanovega drevesa sem uporabil vrsto s prednostjo VrstaPrednost:

Uporabljene metode:

Razred Abeceda iz prebranih podatkov zgradi tabelo vseh nastopajočih znakov

Metode v razredu Abeceda:

Glavni razred je Huffman. Glavno vlogo igra konstruktor:

public Huffman(String imeDat) {
    abc = new Abeceda(imeDat); // preberemo in
    abc.zgradiAbc(); // zgradimo abecedo
    vp = new VrstaPrednost();
    vp.sestaviSeznam(abc.znaki, abc.dolzinaTabele); // sestavimo vrsto s prednostjo

    // zgradimo Huffmanovo drevo
    Vozlisce drevo = null;
    for (int i = 0; i < abc.dolzinaTabele-1; i++) { // za vse znake iz abecede
        drevo = new Vozlisce();
        drevo.levi = vp.najmanjseVozlisce(); // prvo najmanjse vozlisce
        drevo.desni = vp.najmanjseVozlisce(); // naslednje najmanjse vozlisce
        drevo.teza = drevo.levi.teza + drevo.desni.teza; // teza oceta je vsota tez sinov
        drevo.simbol = strazar; // v vozlisce, ki ni list za vsak slucaj postavimo strazarja
                                // seveda tega znaka ne smemo uporabiti v podatkih!
        drevo.koda = "";
        vp.vstavi(drevo); // v vrsto s prednostjo vstavimo drevesce
    } // drevo je zgrajeno
    // zdaj lahko v drevo zapisemo dvojiske kode
    dodajKodo(drevo, abc.znaki, abc.dolzinaTabele, "");
 

Metode:

Primeri

Primer uporabe algoritma je sestavni del kode, ki se nahaja tukaj.

Program predstavi stiskanje podatkov tako, da dano besedilo "stisne" v dvojiški zapis. V tem zapisu so ničle in enke "standardni" znaki. Če bi želeli v resnici stisniti podatke, bi morali "dvojiški" zapis pretvoriti v bite.

 

Program lahko pokličemo z argumentom, ki je ime datoteke, ki jo želimo stisniti. V primeru, da datoteke ne moremo odpreti/prebrati, program vrne napako.

Če program pokličemo brez argumenta, začnemo brati iz standardnega vhoda. Vnos zaključimo s Ctrl Z (Windows) oziroma Ctrl D (Unix), pred tem pa moramo pritisniti Return, da program lahko prebere tudi zadnjo vrstico besedila (sicer je ne more prebrati).

Primeri uporabe:

C:\Seminar2\java Huffman testna.txt

in

C:\Seminar2\java Huffman

in nato vnesemo npr.:

abcdefgaaaaaaaaggggg     aaaa bbbbbbbbbbbb

ctrl Z

Zatem se izpišejo rezultati.