- kodi = biti tjetër nga rryma, gjatësia = 1
- Kodi mirupafshim< base
kod = kod<< 1
kodi = kodi + biti tjetër nga transmetimi
gjatësi = gjatësi + 1 - simbol=simb+baza e kodit]
Me fjalë të tjera, ne do të shtyjmë nga e majta në variablin e kodit pak nga pak nga rryma hyrëse, derisa kodi< base. При этом на каждой итерации будем увеличивать переменную length на 1 (т.е. продвигаться вниз по дереву). Цикл в (2) остановится когда мы определим длину кода (уровень в дереве, на котором находится искомый символ). Остается лишь определить какой именно символ на этом уровне нам нужен.
Supozoni se cikli në (2), pas disa përsëritjesh, është ndalur. Në këtë rast, shprehja (kodi - bazë) është numri rendor i nyjës (karakterit) të kërkuar në nivelin e gjatësisë. Nyja (simboli) i parë në nivelin e gjatësisë në pemë ndodhet në grupin e simboleve në indeks offs. Por ne nuk na intereson karakteri i parë, por karakteri nën numër (kodi - bazë). Prandaj, indeksi i simbolit të dëshiruar në grupin e simboleve është (off + (kodi - bazë)). Me fjalë të tjera, simboli i dëshiruar është simbol=simb + kod - bazë].
Le të marrim një shembull konkret. Duke përdorur algoritmin e mësipërm, ne deshifrojmë mesazhin Z / .
Z / = "0001 1 00001 00000 1 010 011 1 011 1 010 011 0001 1 0010 010 011 011 1 1 1 010 1 1 1 0010 1010 10 10 10 10 10 10 1
- kodi = 0, gjatësia = 1
- kodi = 0< base = 1
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 1 + 1 = 2
kodi = 0< base = 2
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 2 + 1 = 3
kodi = 0< base = 2
kodi = 0<< 1 = 0
kodi = 0 + 1 = 1
gjatësia = 3 + 1 = 4
kod=1=bazë=1 - simbol = simbol = 2 + kod = 1 - bazë = 1] = simbol = A
- kodi = 1, gjatësia = 1
- kod=1=bazë=1
- simbol = simbol = 7 + kod = 1 - bazë = 1] = simbol = H
- kodi = 0, gjatësia = 1
- kodi = 0< base = 1
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 1 + 1 = 2
kodi = 0< base = 2
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 2 + 1 = 3
kodi = 0< base = 2
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 3 + 1 = 4
kodi = 0< base = 1
kodi = 0<< 1 = 0
kodi = 0 + 1 = 1
gjatësia = 4 + 1 = 5
kodi = 1 > baza = 0 - simbol = simbol = 0 + kod = 1 - bazë = 0] = simbol = F
Pra, ne deshifruam 3 karakteret e para: A, H, F. Është e qartë se duke ndjekur këtë algoritëm do të marrim pikërisht mesazhin S.
Llogaritja e gjatësisë së kodit
Për të koduar një mesazh, duhet të dimë kodet e karaktereve dhe gjatësinë e tyre. Siç u përmend në seksionin e mëparshëm, kodet kanonike përcaktohen plotësisht nga gjatësia e tyre. Kështu, detyra jonë kryesore është të llogarisim gjatësinë e kodeve.
Rezulton se kjo detyrë, në shumicën dërrmuese të rasteve, nuk kërkon ndërtimin e qartë të një peme Huffman. Për më tepër, algoritmet që përdorin një paraqitje të brendshme (jo eksplicite) të pemës Huffman janë shumë më efikase për sa i përket shpejtësisë dhe kostove të kujtesës.
Deri më sot, ka shumë algoritme efikase për llogaritjen e gjatësisë së kodeve ( , ). Ne do të kufizohemi në shqyrtimin e vetëm njërit prej tyre. Ky algoritëm është mjaft i thjeshtë, por pavarësisht kësaj është shumë popullor. Përdoret në programe të tilla si zip, gzip, pkzip, bzip2 dhe shumë të tjera.
Le të kthehemi te algoritmi për ndërtimin e pemës Huffman. Në çdo përsëritje, ne kryenim një kërkim linear për dy nyjet me peshën më të vogël. Është e qartë se një radhë prioritare siç është një piramidë (minimumi) është më e përshtatshme për këtë qëllim. Nyja me peshën më të vogël do të ketë më pas prioritetin më të lartë dhe do të jetë në krye të piramidës. Ne paraqesim këtë algoritëm.
Ne përfshijmë të gjithë personazhet e koduar në piramidë.
Ne do të nxjerrim në mënyrë sekuenciale 2 nyje nga piramida (këto do të jenë dy nyjet me peshën më të vogël).
Le të formojmë nyje e re dhe bashkëngjitni në të, si fëmijë, dy nyje të marra nga piramida. Në këtë rast, pesha e nyjës së formuar vendoset e barabartë me shumën e peshave të nyjeve të fëmijëve.
Le të përfshijmë nyjen e krijuar në piramidë.
Nëse ka më shumë se një nyje në piramidë, atëherë përsërisni 2-5.
Ne do të supozojmë se për çdo nyje ruhet një tregues për prindin e saj. Në rrënjën e pemës, ky tregues është vendosur në NULL. Tani le të zgjedhim një nyje fletë (simbol) dhe duke ndjekur treguesit e ruajtur do të ngjitemi lart në pemë derisa treguesi tjetër të bëhet NULL. Kushti i fundit do të thotë që kemi arritur në rrënjën e pemës. Është e qartë se numri i kalimeve nga niveli në nivel është i barabartë me thellësinë e nyjës së gjethes (simbolit), dhe rrjedhimisht gjatësinë e kodit të saj. Duke anashkaluar kështu të gjitha nyjet (karakteret), do të marrim gjatësitë e kodeve të tyre.
Gjatësia maksimale e kodit
Si rregull, kur kodoni, të ashtuquajturat libri i kodeve (Libri i kodeve), një strukturë e thjeshtë të dhënash, në thelb dy vargje: njëra me gjatësi, tjetra me kode. Me fjalë të tjera, kodi (si një varg bit) ruhet në një vend memorie ose regjistër me madhësi fikse (zakonisht 16, 32 ose 64). Për të shmangur një tejmbushje, duhet të jemi të sigurt që kodi do të futet në regjistër.
Rezulton se në një alfabet me karakter N, madhësia maksimale e kodit mund të arrijë (N-1) bit në gjatësi. Me fjalë të tjera, me N=256 (një variant i zakonshëm) mund të marrim një kod me gjatësi 255 bit (edhe pse për këtë skedari duhet të jetë shumë i madh: 2.292654130570773*10^53~=2^177.259)! Është e qartë se një kod i tillë nuk do të futet në regjistër dhe duhet bërë diçka me të.
Së pari, le të zbulojmë se në cilat kushte ndodh një tejmbushje. Le të jetë frekuenca e simbolit i-të e barabartë me numrin e i-të të Fibonaçit. Për shembull: A-1, B-1, C-2, D-3, E-5, F-8, G-13, H-21. Ne ndërtojmë pemën përkatëse Huffman.
ROOT /\ / \ / \ /\ H / \ / \ /\ G / \ / \ /\ F / \ / \ /\ E / \ / \ /\ D / \ / \ /\ C / \ / \ A B
Një pemë e tillë quhet i degjeneruar. Për ta marrë atë, frekuencat e simboleve duhet të rriten të paktën po aq sa numrat Fibonacci ose edhe më shpejt. Edhe pse në praktikë, sipas të dhënave reale, një pemë e tillë është pothuajse e pamundur të merret, është shumë e lehtë ta gjenerosh atë artificialisht. Në çdo rast, ky rrezik duhet të merret parasysh.
Ky problem mund të zgjidhet në dy mënyra të pranueshme. E para prej tyre bazohet në një nga vetitë e kodeve kanonike. Fakti është se në kodin kanonik (varg bit) jo më shumë se bitet më pak të rëndësishme mund të jenë jo zero. Me fjalë të tjera, të gjithë pjesët e tjerë mund të mos ruhen fare, pasi ato janë gjithmonë zero. Në rastin e N=256, mjafton që ne të ruajmë vetëm 8 bitët e poshtëm nga secili kod, duke supozuar se të gjithë bitat e tjerë janë të barabartë me zero. Kjo e zgjidh problemin, por vetëm pjesërisht. Kjo do të komplikojë dhe ngadalësojë shumë kodimin dhe dekodimin. Prandaj, kjo metodë përdoret rrallë në praktikë.
Mënyra e dytë është kufizimi artificial i gjatësisë së kodeve (qoftë gjatë ndërtimit ose pas). Kjo metodë është përgjithësisht e pranuar, kështu që ne do të ndalemi në të më në detaje.
Ekzistojnë dy lloje të algoritmeve kufizuese të gjatësisë së kodit. Heuristik (i përafërt) dhe optimal. Algoritmet e llojit të dytë janë mjaft të vështira për t'u zbatuar dhe, si rregull, kërkojnë më shumë kohë dhe memorie sesa ato të parat. Efikasiteti i një kodi të kufizuar heuristikisht përcaktohet nga devijimi i tij nga ai i kufizuar në mënyrë optimale. Sa më i vogël ky ndryshim, aq më mirë. Vlen të theksohet se për disa algoritme heuristike ky ndryshim është shumë i vogël ( , , ), dhe përveç kësaj, ata shumë shpesh gjenerojnë kodin optimal (edhe pse nuk garantojnë që kjo do të jetë gjithmonë kështu). Për më tepër, që nga në praktikë, tejmbushja ndodh jashtëzakonisht rrallë (përveç nëse vendoset një kufi shumë i rreptë për gjatësinë maksimale të kodit), me një alfabet të vogël, është më e përshtatshme të përdoren metoda heuristike të thjeshta dhe të shpejta.
Ne do të shqyrtojmë një algoritëm heuristik mjaft të thjeshtë dhe shumë të njohur. Ajo ka gjetur rrugën e saj në programe të tilla si zip, gzip, pkzip, bzip2 dhe shumë të tjera.
Problemi i kufizimit të gjatësisë maksimale të kodit është i barabartë me problemin e kufizimit të lartësisë së një peme Huffman. Vini re se, nga ndërtimi, çdo nyje jo gjethe e pemës Huffman ka saktësisht dy fëmijë. Në çdo përsëritje të algoritmit tonë, ne do ta ulim lartësinë e pemës me 1. Pra, le të jetë L gjatësia maksimale e kodit (lartësia e pemës) dhe kërkohet ta kufizojmë atë në L / < L. Më tej , le të jetë RN i nyja e fletës më të djathtë në nivelin i, dhe LN i - më e majta.
Le të fillojmë nga niveli L. Le ta zhvendosim nyjen RN L në vendin e prindit të saj. Sepse nyjet vijnë në çifte, ne duhet të gjejmë një vend për një nyje ngjitur me RN L. Për ta bërë këtë, gjeni nivelin j më afër L që përmban nyjet e gjetheve, të tilla që j < (L-1). Në vend të LN j, do të formojmë një nyje pa gjethe dhe do t'i bashkojmë asaj nyjen LN j dhe nyjen e mbetur pa një çift nga niveli L si fëmijë. Ne zbatojmë të njëjtin veprim për të gjitha çiftet e mbetura të nyjeve në nivelin L. Është e qartë se duke rishpërndarë nyjet në këtë mënyrë, ne kemi ulur lartësinë e pemës sonë me 1. Tani ajo është e barabartë me (L-1). Nëse tani L / < (L-1), atëherë bëni të njëjtën gjë me nivelin (L-1), etj. derisa të arrihet kufiri i kërkuar.
Le të kthehemi te shembulli ynë, ku L=5. Le të kufizojmë gjatësinë maksimale të kodit në L / =4.
ROOT /\ / \ / \ /\ H C E / \ / \ / \ / \ /\ A D G / \ / \ B F
Mund të shihet se në rastin tonë RN L = F, j=3, LN j = C. Fillimisht lëvizim nyjen RN L = F në vend të prindit të tyre.
ROOT /\ / \ / \ /\ H / \ / \ / \ / \ / \ / \ /\ /\ / \ / \ / \ / \ / \ / \ / \ / \ /\ /\ C E / \ / \ / \ / \ F A D G B(nyje e paçiftuar)
Tani në vend LN j = C formojnë një nyje pa gjethe.
ROOT /\ / \ / \ /\ H E / \ / \ / \ / \ / \ / \ F A D G ? ? B(nyje e paçiftuar) C(nyje e paçiftuar)
Lidhni dy nyje të paçiftuara në nyjen e formuar: B Dhe C.
ROOT /\ / \ / \ /\ H / \ / \ / \ / \ / \ / \ / \ / \ / \ /\ /\ / \ / \ / \ / \ / \ / \ / \ / \ /\ /\ /\ E / \ / \ / \ / \ / \ / \ F A D G B C
Kështu, ne kemi kufizuar gjatësinë maksimale të kodit në 4. Është e qartë se duke ndryshuar gjatësitë e kodeve, kemi humbur pak në efikasitet. Pra mesazhi S, i koduar me një kod të tillë, do të ketë një madhësi prej 92 bit, d.m.th. 3 bit më shumë se kodi minimal i tepërt.
Është e qartë se sa më shumë të kufizojmë gjatësinë maksimale të kodit, aq më pak efikas do të jetë kodi. Le të zbulojmë se sa mund të kufizoni gjatësinë maksimale të kodit. Natyrisht jo më e shkurtër se pak.
Llogaritja e kodeve kanonike
Siç e kemi vënë re në mënyrë të përsëritur, gjatësia e kodeve është e mjaftueshme për të gjeneruar vetë kodet. Le të tregojmë se si mund të bëhet. Supozoni se kemi llogaritur tashmë gjatësinë e kodeve dhe kemi numëruar sa kode të secilës gjatësi kemi. Le të jetë L gjatësia maksimale e kodit dhe T i numri i kodeve me gjatësi i.
Llogarit S i - vlera fillestare kodi i gjatësisë i, për të gjitha i nga
S L = 0 (gjithmonë)
S L-1 = (S L + T L) >> 1
S L-2 = (S L-1 + T L-1) >> 1
...
S 1 = 1 (gjithmonë)
Për shembullin tonë L = 5, T 1 .. 5 = (1, 0, 2 ,3, 2).
S 5 = 00000 kosh = 0 dec
S 4 = (S 5 =0 + T 5 =2) >> 1 = (00010 kosh >> 1) = 0001 kosh = 1 dhjetor
S 3 = (S 4 =1 + T 4 =3) >> 1 = (0100 koshi >> 1) = 010 koshi = 2 dhjetor
S 2 = (S 3 =2 + T 3 =2) >> 1 = (100 kosha >> 1) = 10 kosha = 2 dhjetor
S 1 = (S 2 =2 + T 2 =0) >> 1 = (10 kosh >> 1) = 1 kosh = 1 dhjetor
Mund të shihet se S 5 , S 4 , S 3 , S 1 janë pikërisht kodet e karaktereve B, A, C, H. Këto simbole i bashkon fakti se të gjitha janë të parat, secila në nivelin e vet. Me fjalë të tjera, ne kemi gjetur vlerën fillestare të kodit për çdo gjatësi (ose nivel).
Tani le të caktojmë kode për personazhet e mbetur. Kodi i karakterit të parë në nivelin i është S i, i dyti është S i + 1, i treti është S i + 2, e kështu me radhë.
Le të shkruajmë kodet e mbetura për shembullin tonë:
B= S 5 = 00000 kosh | A= S 4 = 0001 kosh | C= S 3 = 010 koshi | H= S 1 = 1 kosh |
F= S 5 + 1 = 00001 kosh | D= S 4 + 1 = 0010 koshi | E= S 3 + 1 = 011 koshi | |
G= S 4 + 2 = 0011 koshi |
Mund të shihet se kemi marrë saktësisht të njëjtat kode sikur të kishim ndërtuar në mënyrë eksplicite pemën kanonike Huffman.
Kalimi i një peme kodi
Në mënyrë që mesazhi i koduar të deshifrohet, dekoderi duhet të ketë të njëjtën pemë koduese (në një formë ose në një tjetër) që është përdorur në kodim. Prandaj, së bashku me të dhënat e koduara, ne jemi të detyruar të ruajmë pemën përkatëse të kodit. Është e qartë se sa më i vogël të jetë, aq më mirë.
Ky problem mund të zgjidhet në disa mënyra. Shumica zgjidhje e dukshme- ruajeni pemën në mënyrë eksplicite (dmth. si një grup i renditur nyjesh dhe treguesish të një lloji ose tjetër). Kjo është ndoshta mënyra më e kotë dhe joefikase. Në praktikë, nuk përdoret.
Mund të ruani një listë të frekuencave të simboleve (p.sh. një fjalor frekuencash). Me ndihmën e tij, dekoderi mund të rindërtojë lehtësisht pemën e kodit. Edhe pse kjo metodë është më pak e kotë se ajo e mëparshme, nuk është më e mira.
Së fundi, mund të përdoret një nga vetitë e kodeve kanonike. Siç u përmend më herët, kodet kanonike përcaktohen plotësisht nga gjatësia e tyre. Me fjalë të tjera, gjithçka që i nevojitet dekoderit është një listë e gjatësive të kodit të karaktereve. Duke pasur parasysh se, mesatarisht, gjatësia e një kodi për një alfabet me karakter N mund të kodohet në bit [(log 2 (log 2 N))], marrim një algoritëm shumë efikas. Ne do të ndalemi në të më në detaje.
Supozoni se madhësia e alfabetit është N=256 dhe e ngjeshim të zakonshmen skedar teksti(ASC II). Me shumë mundësi nuk do të takojmë të gjithë N karakteret e alfabetit tonë në një skedar të tillë. Le të vendosim më pas gjatësinë e kodit të karaktereve që mungojnë zero. Në këtë rast, lista e ruajtur e gjatësisë së kodit do të përmbajë mjaftueshëm numër i madh zero (gjatësitë e kodeve të karaktereve që mungojnë) të grupuara së bashku. Secili grup i tillë mund të kompresohet duke përdorur të ashtuquajturin kodim grupor - RLE (Run - Length - Encoding). Ky algoritëm është jashtëzakonisht i thjeshtë. Në vend të një sekuence M elementësh identikë në një rresht, ne do të ruajmë elementin e parë të kësaj sekuence dhe numrin e përsëritjeve të tij, d.m.th. (M-1). Shembull: RLE("AAAABBBCDDDDDDDD")=A3 B2 C0 D6.
Për më tepër, kjo metodë mund të zgjerohet disi. Mund të aplikojmë Algoritmi RLE jo vetëm për grupet me gjatësi zero, por për të gjithë të tjerët. Kjo mënyrë e transferimit të pemës së kodit është përgjithësisht e pranuar dhe përdoret në shumicën e zbatimeve moderne.
Zbatimi: SHCODEC
Shtojca: biografia e D. Huffman
David Huffman ka lindur në vitin 1925 në Ohio, SHBA. Huffman mori diplomën e tij bachelor në inxhinieri elektrike nga Universiteti Shtetëror Ohio (Universiteti Shtetëror Ohio) në moshën 18 vjeçare. Më pas ai shërbeu në ushtri si oficer mbështetës i radarit në një shkatërrues që ndihmoi në pastrimin e minave në ujërat japoneze dhe kineze pas Luftës së Dytë Botërore. Më pas ai mori një diplomë master nga Universiteti i Ohajos dhe një doktoraturë nga Instituti i Teknologjisë në Massachusetts (MIT). Megjithëse Huffman është më i njohur për zhvillimin e një metode për ndërtimin e kodeve të tepricës minimale, ai gjithashtu dha kontribute të rëndësishme në shumë fusha të tjera (kryesisht në elektronikë). Ai kohe e gjate kryesoi Departamentin e Shkencave Kompjuterike në MIT. Në vitin 1974, tashmë profesor emeritus, dha dorëheqjen. Huffman ka marrë një sërë çmimesh të vlefshme. Në 1999 - Medalja Richard W. Hamming nga Instituti i Inxhinierëve Elektrikë dhe Elektronikë (IEEE) për kontribute të jashtëzakonshme në Teorinë e Informacionit, Medalja Louis E. Levy nga Instituti Franklin për çmimin e tij W. Wallace McDowell, IEEE Computer Society Award, IEEE Golden Jubilee Technology Innovation Award në vitin 1998. Në tetor 1999, në moshën 74-vjeçare, David Huffman vdiq nga kanceri. R.L. Milidiu, A.A. Pessoa, E.S. Laber, "Zbatimi efikas i algoritmit të ngrohjes për ndërtimin e kodeve të prefiksave me gjatësi të kufizuar", Proc. i ALENEX (Punëtori Ndërkombëtare për Inxhinierinë dhe Eksperimentimin e Algoritmeve), pp. 1-17, Springer, Jan. 1999. |
Sot, pak përdorues janë të interesuar për çështjen që lidhet me mekanizmin e kompresimit të skedarëve. Procesi i punës me Kompjuter personal shumë më e lehtë se në të kaluarën.
Sot, pothuajse çdo përdorues që punon me sistemi i skedarëve, përdor arkivat. Sidoqoftë, pak përdorues kanë menduar se si kompresohen skedarët.
Kodet Huffman u bënë opsioni i parë. Ato përdoren ende në arkivues të ndryshëm. Shumica e përdoruesve as nuk mendojnë se sa e lehtë është të kompresosh një skedar sipas kësaj skeme. NË këtë rishikim ne do të shikojmë se si kryhet kompresimi, cilat veçori ndihmojnë në përshpejtimin dhe thjeshtimin e procesit të kodimit. Ne gjithashtu do të përpiqemi të kuptojmë parimet themelore të ndërtimit të një peme kodimi.
Algoritmi: historia
Algoritmi i parë i krijuar për të kryer kodim efikas informacion elektronik, u bë kodi i propozuar nga Huffman në 1952. Është ky kod që mund të merret parasysh sot element bazë shumica e programeve të krijuara për të kompresuar informacionin. Një nga burimet më të njohura që përdorin kodi i dhënë, sot janë Arkivat RAR, ARJ, ZIP. Ky algoritëm përdoret gjithashtu për të kompresuar Imazhet JPEG Dhe objekte grafike. Gjithashtu, të gjitha fakset moderne përdorin një algoritëm kodimi që u shpik në 1952. Përkundër faktit se ka kaluar shumë kohë që nga krijimi i këtij kodi, ai përdoret në mënyrë efektive në pajisjet e stilit të vjetër, si dhe në pajisje dhe predha të reja.
Parimi i kodimit efikas
Algoritmi Huffman bazohet në një skemë që ju lejon të zëvendësoni karakteret më të mundshme dhe më të shpeshta me kode sistemi binar. Ato karaktere që janë më pak të zakonshme zëvendësohen me kode të gjata. Tranzicioni në kodet e gjata Huffman kryhet vetëm pasi sistemi përdor të gjitha vlerat minimale. Kjo teknikë bën të mundur minimizimin e gjatësisë së kodit për simbol të mesazhit origjinal. NË këtë rast E veçanta është se duhet të dihen tashmë probabilitetet e shfaqjes së shkronjave në fillim të kodimit. Mesazhi përfundimtar do të përbëhet prej tyre. Bazuar në këtë informacion, kryhet ndërtimi i pemës së kodit Huffman. Në bazë të tij do të kryhet procesi i kodimit të shkronjave në arkiv.
Kodi Huffman: shembull
Për të ilustruar algoritmin Huffman, merrni parasysh një version grafik të ndërtimit të një peme kodi. Per te perdorur këtë metodë ishte më efikase, është e nevojshme të sqarohet përkufizimi i disa vlerave që janë të nevojshme për konceptin e kësaj metode. I gjithë grupi i shumë nyjeve dhe harqeve që drejtohen nga nyja në nyje quhet graf. Vetë pema është një grafik me një grup karakteristikash specifike. Çdo nyje duhet të përmbajë jo më shumë se një nga të gjitha harqet. Një nga nyjet duhet të jetë rrënja e pemës. Kjo do të thotë që nuk duhet të përfshijë fare harqe. Nëse filloni nga rrënja e lëvizjes përgjatë harqeve, atëherë ky proces duhet t'ju lejojë të arrini në çdo nyje.
Kodet Huffman përfshijnë gjithashtu një gjë të tillë si një gjethe e një peme. Ai përfaqëson një nyje nga e cila nuk duhet të dalë asnjë hark. Nëse dy nyje janë të lidhura me një hark, atëherë njëri prej tyre është një prind dhe tjetri është një fëmijë. Nëse dy nyje kanë një nyje të përbashkët prind, atëherë ato quhen nyje si motra. Nëse, përveç gjetheve, nyjet kanë disa harqe, atëherë një pemë e tillë quhet binare. Kjo është pikërisht ajo që është pema Huffman. Një tipar i nyjeve të kësaj strukture është se pesha e secilit prind është e barabartë me shumën e peshave të fëmijëve të nyjeve.
Pema Huffman: algoritmi i ndërtimit
Ndërtimi i kodit Huffman kryhet nga shkronjat e alfabetit të hyrjes. Formohet një listë e nyjeve të lira në pemën e kodit të ardhshëm. Në këtë listë, pesha e secilës nyje duhet të jetë e njëjtë me probabilitetin e shfaqjes së letrës së mesazhit që korrespondon me nyja e dhënë. Midis disa nyjeve të lira, zgjidhet ajo që peshon më pak. Nëse në të njëjtën kohë vërehen tregues minimalë në disa nyje, atëherë mund të zgjidhni lirshëm çdo palë. Pas kësaj, krijohet nyja mëmë. Duhet të peshojë sa shuma e çiftit të dhënë të nyjeve. Më pas, prindi dërgohet në listë me nyje të lira. Fëmijët hiqen. Në këtë rast, harqet marrin treguesit përkatës, zero dhe njëshe. Ky proces përsëritet aq herë sa nevojitet për të lënë vetëm një nyje. Pas kësaj, shifrat binare shkruhen nga lart poshtë.
Si të përmirësoni efikasitetin e kompresimit
Për të rritur efikasitetin e kompresimit, gjatë ndërtimit të pemës së kodit, është e nevojshme të përdoren të gjitha të dhënat në lidhje me probabilitetin e shfaqjes së shkronjave në një skedar të caktuar që i bashkëngjitet pemës. Ato nuk duhet të lejohen të shpërndahen në një numër të madh dokumentesh tekstuale. Nëse ecni nëpër dosjen e dhënë, atëherë mund të merrni statistika se sa shpesh mund të gjenden shkronjat nga objekti që do të kompresohet.
Si të shpejtoni procesin e kompresimit
Për të shpejtuar algoritmin, përcaktimi i shkronjave duhet të kryhet jo nga treguesit e shfaqjes së shkronjave të caktuara, por nga shpeshtësia e shfaqjes së tyre. Falë kësaj, algoritmi bëhet më i thjeshtë dhe puna me të përshpejtohet ndjeshëm. Gjithashtu bën të mundur shmangien e operacioneve të ndarjes dhe me pikë lundruese. Gjithashtu, kur punoni në këtë mënyrë, algoritmi nuk mund të ndryshohet. Kjo është kryesisht për shkak të faktit se probabilitetet janë drejtpërdrejt proporcionale me frekuencat. Vlen gjithashtu t'i kushtohet vëmendje faktit që pesha përfundimtare e nyjës rrënjë do të jetë e barabartë me shumën e numrit të shkronjave në objektin që do të përpunohet.
Prodhimi
Kodet Huffman janë një algoritëm i thjeshtë dhe i krijuar prej kohësh që përdoret ende sot në shumë programe të njohura. Thjeshtësia dhe qartësia e këtij kodi ju lejon të arrini kompresim efektiv skedarë të çdo madhësie.
Një metodë relativisht e thjeshtë e kompresimit të të dhënave mund të bëhet duke krijuar të ashtuquajturat pemë Huffman në një skedar dhe të përdoret për ta kompresuar atë dhe për të dekompresuar të dhënat në të. Për shumicën e aplikacioneve, përdoren pemë binare Huffman (për shembull, secila nyje është ose një gjethe ose ka saktësisht dy nënnyje). Megjithatë, është e mundur të ndërtohen pemë Huffman me numër arbitrar nënpemë (për shembull, treshe ose, in rast i përgjithshëm, N-ic pemë).
Pema Huffman për një skedar që përmban Z personazhe të ndryshme Ajo ka Z gjethet. Rruga nga rrënja te fleta që përfaqëson një karakter të caktuar përcakton kodimin dhe çdo hap në shtegun e fletës përcakton kodimin (i cili mund të jetë 0 , 1 , ..., (N-1)). Duke vendosur karaktere që shfaqen shpesh më afër rrënjës, dhe karaktere që shfaqen më rrallë më larg rrënjës, arrihet ngjeshja e dëshiruar. Në mënyrë të rreptë, një pemë e tillë do të jetë një pemë Huffman vetëm nëse numri minimal N karaktere -ic për të koduar skedarin e dhënë.
Në këtë problem, ne do të shqyrtojmë vetëm pemët ku secila nyje është ose një nyje e brendshme ose një fletë koduese e karaktereve dhe nuk ka gjethe të izoluara që nuk kodojnë një karakter.
Figura më poshtë tregon një shembull të një peme treshe Huffman, simbolet " a"Dhe" e"E koduar me një karakter të vetëm tresh; karaktere më pak të zakonshme" s"Dhe" fq"janë të koduara duke përdorur dy karaktere treshe dhe karakteret më të rralla" x", "q"Dhe" y" janë të koduara duke përdorur tre karaktere treshe secila.
Sigurisht, nëse duam, mund ta zgjerojmë listën N karakteret -ic pastaj kthehen, është e rëndësishme të dini se cila pemë përdoret për të kompresuar të dhënat. Kjo mund të bëhet në disa mënyra. Në këtë detyrë, ne do të përdorim metodën e mëposhtme: rryma hyrëse do të paraprihet nga një kokë e përbërë nga vlera të koduara të karaktereve Z të vendosura në skedari burimor sipas rendit leksikografik.
Njohja e numrit të karaktereve hyrëse Z, kuptimi N, duke treguar " N-ariteti" i pemës Huffman dhe vetë kokës, është e nevojshme të gjendet vlera kryesore e karaktereve të koduara.
Fut te dhenat
Hyrja fillon me një numër të plotë T, i vendosur në një linjë të veçantë dhe që tregon numrin e rasteve të testimit të mëvonshëm. Më pas, secila prej T rastet e testimit, secila e vendosur në 3 -x rreshtat si më poshtë:
- Numri i karaktereve të dallueshme në rastin e testit Z (2 ≤ Z ≤ 20 );
- Numri N, duke treguar " N-ariteti" i pemës Huffman ( 2 ≤ N ≤ 10 );
- Një varg që përfaqëson kokën e mesazhit të marrë, çdo karakter do të jetë një shifër në interval . Kjo linjë do të përmbajë më pak 200 personazhet.
Shënim : Edhe pse e rrallë, është e mundur që një titull të ketë interpretime të shumta kur transkriptohet (për shembull, për titullin " 010011101100 ", dhe vlerat Z = 5 Dhe N=2). Është e garantuar që në të gjitha rastet e testimit të propozuara në të dhënat hyrëse, ekziston një zgjidhje unike.
Prodhimi
Për secilën prej T rastet e testimit të prodhimit Z linjat që japin versionin e deshifruar të secilit Z personazhet në rend rritës. Përdorni formatin origjinal-> kodim, ku origjinale- kjo numër dhjetor në varg dhe vargun përkatës të koduar të shifrave të koduara për ato karaktere (secila shifër ≥ 0 Dhe< N).
- kodi = biti tjetër nga rryma, gjatësia = 1
- Kodi mirupafshim< base
kod = kod<< 1
kodi = kodi + biti tjetër nga transmetimi
gjatësi = gjatësi + 1 - simbol=simb+baza e kodit]
Me fjalë të tjera, ne do të shtyjmë nga e majta në variablin e kodit pak nga pak nga rryma hyrëse, derisa kodi< base. При этом на каждой итерации будем увеличивать переменную length на 1 (т.е. продвигаться вниз по дереву). Цикл в (2) остановится когда мы определим длину кода (уровень в дереве, на котором находится искомый символ). Остается лишь определить какой именно символ на этом уровне нам нужен.
Supozoni se cikli në (2), pas disa përsëritjesh, është ndalur. Në këtë rast, shprehja (kodi - bazë) është numri rendor i nyjës (karakterit) të kërkuar në nivelin e gjatësisë. Nyja (simboli) i parë në nivelin e gjatësisë në pemë ndodhet në grupin e simboleve në indeks offs. Por ne nuk na intereson karakteri i parë, por karakteri nën numër (kodi - bazë). Prandaj, indeksi i simbolit të dëshiruar në grupin e simboleve është (off + (kodi - bazë)). Me fjalë të tjera, simboli i dëshiruar është simbol=simb + kod - bazë].
Le të marrim një shembull konkret. Duke përdorur algoritmin e mësipërm, ne deshifrojmë mesazhin Z / .
Z / = "0001 1 00001 00000 1 010 011 1 011 1 010 011 0001 1 0010 010 011 011 1 1 1 010 1 1 1 0010 1010 10 10 10 10 10 10 1
- kodi = 0, gjatësia = 1
- kodi = 0< base = 1
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 1 + 1 = 2
kodi = 0< base = 2
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 2 + 1 = 3
kodi = 0< base = 2
kodi = 0<< 1 = 0
kodi = 0 + 1 = 1
gjatësia = 3 + 1 = 4
kod=1=bazë=1 - simbol = simbol = 2 + kod = 1 - bazë = 1] = simbol = A
- kodi = 1, gjatësia = 1
- kod=1=bazë=1
- simbol = simbol = 7 + kod = 1 - bazë = 1] = simbol = H
- kodi = 0, gjatësia = 1
- kodi = 0< base = 1
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 1 + 1 = 2
kodi = 0< base = 2
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 2 + 1 = 3
kodi = 0< base = 2
kodi = 0<< 1 = 0
kodi = 0 + 0 = 0
gjatësia = 3 + 1 = 4
kodi = 0< base = 1
kodi = 0<< 1 = 0
kodi = 0 + 1 = 1
gjatësia = 4 + 1 = 5
kodi = 1 > baza = 0 - simbol = simbol = 0 + kod = 1 - bazë = 0] = simbol = F
Pra, ne deshifruam 3 karakteret e para: A, H, F. Është e qartë se duke ndjekur këtë algoritëm do të marrim pikërisht mesazhin S.
Llogaritja e gjatësisë së kodit
Për të koduar një mesazh, duhet të dimë kodet e karaktereve dhe gjatësinë e tyre. Siç u përmend në seksionin e mëparshëm, kodet kanonike përcaktohen plotësisht nga gjatësia e tyre. Kështu, detyra jonë kryesore është të llogarisim gjatësinë e kodeve.
Rezulton se kjo detyrë, në shumicën dërrmuese të rasteve, nuk kërkon ndërtimin e qartë të një peme Huffman. Për më tepër, algoritmet që përdorin një paraqitje të brendshme (jo eksplicite) të pemës Huffman janë shumë më efikase për sa i përket shpejtësisë dhe kostove të kujtesës.
Deri më sot, ka shumë algoritme efikase për llogaritjen e gjatësisë së kodeve ( , ). Ne do të kufizohemi në shqyrtimin e vetëm njërit prej tyre. Ky algoritëm është mjaft i thjeshtë, por pavarësisht kësaj është shumë popullor. Përdoret në programe të tilla si zip, gzip, pkzip, bzip2 dhe shumë të tjera.
Le të kthehemi te algoritmi për ndërtimin e pemës Huffman. Në çdo përsëritje, ne kryenim një kërkim linear për dy nyjet me peshën më të vogël. Është e qartë se një radhë prioritare siç është një piramidë (minimumi) është më e përshtatshme për këtë qëllim. Nyja me peshën më të vogël do të ketë më pas prioritetin më të lartë dhe do të jetë në krye të piramidës. Ne paraqesim këtë algoritëm.
Ne përfshijmë të gjithë personazhet e koduar në piramidë.
Ne do të nxjerrim në mënyrë sekuenciale 2 nyje nga piramida (këto do të jenë dy nyjet me peshën më të vogël).
Le të formojmë një nyje të re dhe t'i bashkojmë, si fëmijë, dy nyje të marra nga piramida. Në këtë rast, pesha e nyjës së formuar vendoset e barabartë me shumën e peshave të nyjeve të fëmijëve.
Le të përfshijmë nyjen e krijuar në piramidë.
Nëse ka më shumë se një nyje në piramidë, atëherë përsërisni 2-5.
Ne do të supozojmë se për çdo nyje ruhet një tregues për prindin e saj. Në rrënjën e pemës, ky tregues është vendosur në NULL. Tani le të zgjedhim një nyje fletë (simbol) dhe duke ndjekur treguesit e ruajtur do të ngjitemi lart në pemë derisa treguesi tjetër të bëhet NULL. Kushti i fundit do të thotë që kemi arritur në rrënjën e pemës. Është e qartë se numri i kalimeve nga niveli në nivel është i barabartë me thellësinë e nyjës së gjethes (simbolit), dhe rrjedhimisht gjatësinë e kodit të saj. Duke anashkaluar kështu të gjitha nyjet (karakteret), do të marrim gjatësitë e kodeve të tyre.
Gjatësia maksimale e kodit
Si rregull, kur kodoni, të ashtuquajturat libri i kodeve (Libri i kodeve), një strukturë e thjeshtë të dhënash, në thelb dy vargje: njëra me gjatësi, tjetra me kode. Me fjalë të tjera, kodi (si një varg bit) ruhet në një vend memorie ose regjistër me madhësi fikse (zakonisht 16, 32 ose 64). Për të shmangur një tejmbushje, duhet të jemi të sigurt që kodi do të futet në regjistër.
Rezulton se në një alfabet me karakter N, madhësia maksimale e kodit mund të arrijë (N-1) bit në gjatësi. Me fjalë të tjera, me N=256 (një variant i zakonshëm) mund të marrim një kod me gjatësi 255 bit (edhe pse për këtë skedari duhet të jetë shumë i madh: 2.292654130570773*10^53~=2^177.259)! Është e qartë se një kod i tillë nuk do të futet në regjistër dhe duhet bërë diçka me të.
Së pari, le të zbulojmë se në cilat kushte ndodh një tejmbushje. Le të jetë frekuenca e simbolit i-të e barabartë me numrin e i-të të Fibonaçit. Për shembull: A-1, B-1, C-2, D-3, E-5, F-8, G-13, H-21. Ne ndërtojmë pemën përkatëse Huffman.
ROOT /\ / \ / \ /\ H / \ / \ /\ G / \ / \ /\ F / \ / \ /\ E / \ / \ /\ D / \ / \ /\ C / \ / \ A B
Një pemë e tillë quhet i degjeneruar. Për ta marrë atë, frekuencat e simboleve duhet të rriten të paktën po aq sa numrat Fibonacci ose edhe më shpejt. Edhe pse në praktikë, sipas të dhënave reale, një pemë e tillë është pothuajse e pamundur të merret, është shumë e lehtë ta gjenerosh atë artificialisht. Në çdo rast, ky rrezik duhet të merret parasysh.
Ky problem mund të zgjidhet në dy mënyra të pranueshme. E para prej tyre bazohet në një nga vetitë e kodeve kanonike. Fakti është se në kodin kanonik (varg bit) jo më shumë se bitet më pak të rëndësishme mund të jenë jo zero. Me fjalë të tjera, të gjithë pjesët e tjerë mund të mos ruhen fare, pasi ato janë gjithmonë zero. Në rastin e N=256, mjafton që ne të ruajmë vetëm 8 bitët e poshtëm nga secili kod, duke supozuar se të gjithë bitat e tjerë janë të barabartë me zero. Kjo e zgjidh problemin, por vetëm pjesërisht. Kjo do të komplikojë dhe ngadalësojë shumë kodimin dhe dekodimin. Prandaj, kjo metodë përdoret rrallë në praktikë.
Mënyra e dytë është kufizimi artificial i gjatësisë së kodeve (qoftë gjatë ndërtimit ose pas). Kjo metodë është përgjithësisht e pranuar, kështu që ne do të ndalemi në të më në detaje.
Ekzistojnë dy lloje të algoritmeve kufizuese të gjatësisë së kodit. Heuristik (i përafërt) dhe optimal. Algoritmet e llojit të dytë janë mjaft të vështira për t'u zbatuar dhe, si rregull, kërkojnë më shumë kohë dhe memorie sesa ato të parat. Efikasiteti i një kodi të kufizuar heuristikisht përcaktohet nga devijimi i tij nga ai i kufizuar në mënyrë optimale. Sa më i vogël ky ndryshim, aq më mirë. Vlen të theksohet se për disa algoritme heuristike ky ndryshim është shumë i vogël ( , , ), dhe përveç kësaj, ata shumë shpesh gjenerojnë kodin optimal (edhe pse nuk garantojnë që kjo do të jetë gjithmonë kështu). Për më tepër, që nga në praktikë, tejmbushja ndodh jashtëzakonisht rrallë (përveç nëse vendoset një kufi shumë i rreptë për gjatësinë maksimale të kodit), me një alfabet të vogël, është më e përshtatshme të përdoren metoda heuristike të thjeshta dhe të shpejta.
Ne do të shqyrtojmë një algoritëm heuristik mjaft të thjeshtë dhe shumë të njohur. Ajo ka gjetur rrugën e saj në programe të tilla si zip, gzip, pkzip, bzip2 dhe shumë të tjera.
Problemi i kufizimit të gjatësisë maksimale të kodit është i barabartë me problemin e kufizimit të lartësisë së një peme Huffman. Vini re se, nga ndërtimi, çdo nyje jo gjethe e pemës Huffman ka saktësisht dy fëmijë. Në çdo përsëritje të algoritmit tonë, ne do ta ulim lartësinë e pemës me 1. Pra, le të jetë L gjatësia maksimale e kodit (lartësia e pemës) dhe kërkohet ta kufizojmë atë në L / < L. Më tej , le të jetë RN i nyja e fletës më të djathtë në nivelin i, dhe LN i - më e majta.
Le të fillojmë nga niveli L. Le ta zhvendosim nyjen RN L në vendin e prindit të saj. Sepse nyjet vijnë në çifte, ne duhet të gjejmë një vend për një nyje ngjitur me RN L. Për ta bërë këtë, gjeni nivelin j më afër L që përmban nyjet e gjetheve, të tilla që j < (L-1). Në vend të LN j, do të formojmë një nyje pa gjethe dhe do t'i bashkojmë asaj nyjen LN j dhe nyjen e mbetur pa një çift nga niveli L si fëmijë. Ne zbatojmë të njëjtin veprim për të gjitha çiftet e mbetura të nyjeve në nivelin L. Është e qartë se duke rishpërndarë nyjet në këtë mënyrë, ne kemi ulur lartësinë e pemës sonë me 1. Tani ajo është e barabartë me (L-1). Nëse tani L / < (L-1), atëherë bëni të njëjtën gjë me nivelin (L-1), etj. derisa të arrihet kufiri i kërkuar.
Le të kthehemi te shembulli ynë, ku L=5. Le të kufizojmë gjatësinë maksimale të kodit në L / =4.
ROOT /\ / \ / \ /\ H C E / \ / \ / \ / \ /\ A D G / \ / \ B F
Mund të shihet se në rastin tonë RN L = F, j=3, LN j = C. Fillimisht lëvizim nyjen RN L = F në vend të prindit të tyre.
ROOT /\ / \ / \ /\ H / \ / \ / \ / \ / \ / \ /\ /\ / \ / \ / \ / \ / \ / \ / \ / \ /\ /\ C E / \ / \ / \ / \ F A D G B(nyje e paçiftuar)
Tani në vend LN j = C formojnë një nyje pa gjethe.
ROOT /\ / \ / \ /\ H E / \ / \ / \ / \ / \ / \ F A D G ? ? B(nyje e paçiftuar) C(nyje e paçiftuar)
Lidhni dy nyje të paçiftuara në nyjen e formuar: B Dhe C.
ROOT /\ / \ / \ /\ H / \ / \ / \ / \ / \ / \ / \ / \ / \ /\ /\ / \ / \ / \ / \ / \ / \ / \ / \ /\ /\ /\ E / \ / \ / \ / \ / \ / \ F A D G B C
Kështu, ne kemi kufizuar gjatësinë maksimale të kodit në 4. Është e qartë se duke ndryshuar gjatësitë e kodeve, kemi humbur pak në efikasitet. Pra mesazhi S, i koduar me një kod të tillë, do të ketë një madhësi prej 92 bit, d.m.th. 3 bit më shumë se kodi minimal i tepërt.
Është e qartë se sa më shumë të kufizojmë gjatësinë maksimale të kodit, aq më pak efikas do të jetë kodi. Le të zbulojmë se sa mund të kufizoni gjatësinë maksimale të kodit. Natyrisht jo më e shkurtër se pak.
Llogaritja e kodeve kanonike
Siç e kemi vënë re në mënyrë të përsëritur, gjatësia e kodeve është e mjaftueshme për të gjeneruar vetë kodet. Le të tregojmë se si mund të bëhet. Supozoni se kemi llogaritur tashmë gjatësinë e kodeve dhe kemi numëruar sa kode të secilës gjatësi kemi. Le të jetë L gjatësia maksimale e kodit dhe T i numri i kodeve me gjatësi i.
Llogaritni S i - vlerën fillestare të kodit të gjatësisë i, për të gjitha i nga
S L = 0 (gjithmonë)
S L-1 = (S L + T L) >> 1
S L-2 = (S L-1 + T L-1) >> 1
...
S 1 = 1 (gjithmonë)
Për shembullin tonë L = 5, T 1 .. 5 = (1, 0, 2 ,3, 2).
S 5 = 00000 kosh = 0 dec
S 4 = (S 5 =0 + T 5 =2) >> 1 = (00010 kosh >> 1) = 0001 kosh = 1 dhjetor
S 3 = (S 4 =1 + T 4 =3) >> 1 = (0100 koshi >> 1) = 010 koshi = 2 dhjetor
S 2 = (S 3 =2 + T 3 =2) >> 1 = (100 kosha >> 1) = 10 kosha = 2 dhjetor
S 1 = (S 2 =2 + T 2 =0) >> 1 = (10 kosh >> 1) = 1 kosh = 1 dhjetor
Mund të shihet se S 5 , S 4 , S 3 , S 1 janë pikërisht kodet e karaktereve B, A, C, H. Këto simbole i bashkon fakti se të gjitha janë të parat, secila në nivelin e vet. Me fjalë të tjera, ne kemi gjetur vlerën fillestare të kodit për çdo gjatësi (ose nivel).
Tani le të caktojmë kode për personazhet e mbetur. Kodi i karakterit të parë në nivelin i është S i, i dyti është S i + 1, i treti është S i + 2, e kështu me radhë.
Le të shkruajmë kodet e mbetura për shembullin tonë:
B= S 5 = 00000 kosh | A= S 4 = 0001 kosh | C= S 3 = 010 koshi | H= S 1 = 1 kosh |
F= S 5 + 1 = 00001 kosh | D= S 4 + 1 = 0010 koshi | E= S 3 + 1 = 011 koshi | |
G= S 4 + 2 = 0011 koshi |
Mund të shihet se kemi marrë saktësisht të njëjtat kode sikur të kishim ndërtuar në mënyrë eksplicite pemën kanonike Huffman.
Kalimi i një peme kodi
Në mënyrë që mesazhi i koduar të deshifrohet, dekoderi duhet të ketë të njëjtën pemë koduese (në një formë ose në një tjetër) që është përdorur në kodim. Prandaj, së bashku me të dhënat e koduara, ne jemi të detyruar të ruajmë pemën përkatëse të kodit. Është e qartë se sa më i vogël të jetë, aq më mirë.
Ky problem mund të zgjidhet në disa mënyra. Zgjidhja më e dukshme është ruajtja e pemës në mënyrë eksplicite (d.m.th. si një grup i renditur nyjesh dhe treguesish të një lloji ose tjetër). Kjo është ndoshta mënyra më e kotë dhe joefikase. Në praktikë, nuk përdoret.
Mund të ruani një listë të frekuencave të simboleve (p.sh. një fjalor frekuencash). Me ndihmën e tij, dekoderi mund të rindërtojë lehtësisht pemën e kodit. Edhe pse kjo metodë është më pak e kotë se ajo e mëparshme, nuk është më e mira.
Së fundi, mund të përdoret një nga vetitë e kodeve kanonike. Siç u përmend më herët, kodet kanonike përcaktohen plotësisht nga gjatësia e tyre. Me fjalë të tjera, gjithçka që i nevojitet dekoderit është një listë e gjatësive të kodit të karaktereve. Duke pasur parasysh se, mesatarisht, gjatësia e një kodi për një alfabet me karakter N mund të kodohet në bit [(log 2 (log 2 N))], marrim një algoritëm shumë efikas. Ne do të ndalemi në të më në detaje.
Supozoni se madhësia e alfabetit është N=256 dhe ne po kompresojmë një skedar teksti të thjeshtë (ASCII). Me shumë mundësi nuk do të takojmë të gjithë N karakteret e alfabetit tonë në një skedar të tillë. Le ta vendosim gjatësinë e kodit të karaktereve që mungojnë në zero. Në këtë rast, lista e ruajtur e gjatësisë së kodeve do të përmbajë një numër mjaft të madh zerosh (gjatësitë e kodeve të karaktereve që mungojnë) të grupuara së bashku. Secili grup i tillë mund të kompresohet duke përdorur të ashtuquajturin kodim grupor - RLE (Run - Length - Encoding). Ky algoritëm është jashtëzakonisht i thjeshtë. Në vend të një sekuence M elementësh identikë në një rresht, ne do të ruajmë elementin e parë të kësaj sekuence dhe numrin e përsëritjeve të tij, d.m.th. (M-1). Shembull: RLE("AAAABBBCDDDDDDDD")=A3 B2 C0 D6.
Për më tepër, kjo metodë mund të zgjerohet disi. Ne mund të aplikojmë algoritmin RLE jo vetëm për grupet me gjatësi zero, por për të gjithë të tjerët. Kjo mënyrë e transferimit të pemës së kodit është përgjithësisht e pranuar dhe përdoret në shumicën e zbatimeve moderne.
Zbatimi: SHCODEC
Shtojca: biografia e D. Huffman
David Huffman ka lindur në vitin 1925 në Ohio, SHBA. Huffman mori diplomën e tij bachelor në inxhinieri elektrike nga Universiteti Shtetëror i Ohajos në moshën 18-vjeçare. Më pas ai shërbeu në ushtri si oficer mbështetës i radarit në një shkatërrues që ndihmoi në pastrimin e minave në ujërat japoneze dhe kineze pas Luftës së Dytë Botërore. Më pas ai mori një diplomë master nga Universiteti i Ohajos dhe një doktoraturë nga Instituti i Teknologjisë në Massachusetts (MIT). Megjithëse Huffman është më i njohur për zhvillimin e një metode për ndërtimin e kodeve të tepricës minimale, ai gjithashtu dha kontribute të rëndësishme në shumë fusha të tjera (kryesisht në elektronikë). Ai ishte një kryetar për një kohë të gjatë i Departamentit të Shkencave Kompjuterike në MIT. Në vitin 1974, tashmë profesor emeritus, dha dorëheqjen. Huffman ka marrë një sërë çmimesh të vlefshme. Në 1999 - Medalja Richard W. Hamming nga Instituti i Inxhinierëve Elektrikë dhe Elektronikë (IEEE) për kontribute të jashtëzakonshme në Teorinë e Informacionit, Medalja Louis E. Levy nga Instituti Franklin për çmimin e tij W. Wallace McDowell, IEEE Computer Society Award, IEEE Golden Jubilee Technology Innovation Award në vitin 1998. Në tetor 1999, në moshën 74-vjeçare, David Huffman vdiq nga kanceri. |