Sunteți pe pagina 1din 6

4/22/13

Laboratorul 8

Constructia unui arbore de codificare optimala


Majoritatea algoritmilor de compresie se bazeaza pe generarea unor coduri binare cu lungime variabila. Codurile mai scurte sunt asociate caracterelor (simbolurilor) care apar cel mai frecvent, iar cele mai lungi acelor caractere care apar cu frecventa scazuta. Alegerea setului de coduri cu lungime variabila trebuie sa asigure decodificarea corecta a informatiei. Conditia de decodificare corecta este aceea ca niciunul din coduri sa nu fie obtinut prin adaugarea unor biti la un cod deja existent. De exemplu, urmatorul set de 3 coduri asociat caracterelor {A, B, si C}: A: 0 B: 01 C: 10 nu respecta conditia de decodificare corecta deoarece codul asociat lui B (01) este obtinut din codul lui A (0) plus un bit (1). Din acest motiv, sirul de biti 010 poate fi decodificat fie "BA" (01_0) fie "AC" (0_10). Cel mai simplu mod de a genera un set corect de coduri este utilizarea unui arbore binar de codificare. Frunzele unui astfel de arbore corespund caracterelor care se codifica, codul asociat fiecarui caracter obtinandu-se prin parcurgerea arborelui de la radacina pina la frunza corespunzatoare caracterului, o trecere in nodul subordonat din stanga corespunde unui bit "0" iar una in cel din dreapta unui bit "1". De exemplu, pentru arborele din figura urmatoare:

codurile corespunzatoare celor 3 caractere sunt: A: 0 B: 10 C: 11 O alta problema este generarea arborelui de codificare astfel incat lungimile codurilor sa fie corelate cu frecventele de aparitie ale caracterelor in mesajul care trebuie codificat. Solutia acestei probleme este data de algoritmul Huffman. Algoritmul Huffman are ca date initiale setul de caractere pentru care se doreste generarea arborelui de codificare precum si numarul de aparitii ale fiecaruia. Initial, algoritmul creeaza cate un nod terminal (frunza) pentru fiecare caracter. Campul de informatiei asociat acestor noduri contine atat caracterul corespunzator, cat si numarul de aparitii ale acestuia. Aceste noduri sunt organizate intr-o lista (lista nodurilor ramase de prelucrat). Algoritmul de generare a arborelui este urmatorul:
file:///C:/work/UPB/materiale cursuri/SDA/Laborator8/lab8.htm 1/6

4/22/13

Laboratorul 8

r e p e t a { 1 .c a u t ai nl i s t an o d u r i l o rr a m a s ec e l ed o u an o d u r i( N 1s iN 2 )c a r ea u c e lm a im i cn u m a rd ea p a r i t i i ; 2 .c r e e a z au nn o dn o u( N 1 2 )l ac a r ec o n e c t e a z an o d u r i l eN 1s iN 2c a s u b o r d o n a t i . 3 .c o m p l e t e a z an u m a r u ld ea p a r i t i ia ln o d u l u iN 1 2c af i i n ds u m aa p a r i t i i l o r c e l o rd o u an o d u r is u b o r d o n a t e( N 1s iN 2 ) ; 4 .e l i m i n an o d u r i l eN 1s iN 2d i nl i s t an o d u r i l o rr a m a s es ia d a u g al a a c e a s t al i s t an o d u lN 1 2 }p a n ac a n dl i s t an o d u r i l o rr a m a s ea r eu ns i n g u re l e m e n t

La terminarea algoritmului, nodul ramas in lista este de fapt radacina arborelui de codificare, toate celelalte noduri fiind conectate in arbore. Un exemplu de aplicare a acestui algoritm pentru un set de 5 caractere (A,B,C,D si E} avind frecventele de aparitie {100, 20, 18, 22 respectiv 15} este prezentat in cele ce urmeaza. Conventia de desenare pentru un nod este un dreptunghi avind in interior scris caracterul corespunzator nodului (doar in cazul celor terminale) si numarul de aparitii ale nodului.

In primul pas se cauta cele doua noduri care au cele mai mici numere de aparitie ('E' si 'C'), se creeaza un nod nou la care acestea se conecteaza ca subordonati. Nodurile 'E' si 'C' sunt scoase din lista si inlocuite cu nodul nou creat.

In continuare procesul se repeta astfel:

file:///C:/work/UPB/materiale cursuri/SDA/Laborator8/lab8.htm

2/6

4/22/13

Laboratorul 8

TEMA: Sa se scrie o procedura care genereaza arborele de codificare optimala pe baza algoritmului Huffman. Procedura primeste ca parametru un sir de caractere (textul care va fi codificat). Prototipul functiei va fi:
v o i dg e n e r e a z a _ a r b o r e ( c h a r* s i r )

Pentru nodurile arborelui se va folosi urmatoarea structura de date:


t y p e d e fs t r u c ts t r _ n o d {u n s i g n e dc h a r u n s i g n e di n t s t r u c ts t r _ n o d s t r u c ts t r _ n o d s t r u c ts t r _ n o d s t r u c ts t r _ n o d } n o d ;
file:///C:/work/UPB/materiale cursuri/SDA/Laborator8/lab8.htm

c a r a c t e r ; n r _ a p a r i t i i ; s t i n g a ; d r e a p t a ; s u s ; n o d _ u r m a t o r ;

3/6

4/22/13

Laboratorul 8

in acesta structura, campurile au urmatoarele semnificatii:


< c a r a c t e r >-

este caracterul corespunzator nodului (numai pentru nodurile terminale); < n r _ a p a r i t i i >- reprezinta numarul de aparitii ale nodului (pentru nodurile terminare corespunde numarului de aparitii ale caracterului corespunzator iar pentru nodurile intermediare este suma aparitiilor nodurilor subordonate); < s t i n g a >- legatura catre nodul subordonat stinga (pointer catre structura de date corespunzatoare nodului); < d r e a p t a >- legatura catre nodul subordonat dreapta (pointer catre structura de date corespunzatoare nodului); < s u s >- legatura catre nodul superior (pointer catre structura de date corespunzatoare nodului); < n o d _ u r m a t o r >- legatura catre nodul urmator din lista de noduri ramase. Deasemenea, se va utiliza o variabila care sa indice inceputul listei de noduri ramase declarata astfel:
n o d * l i s t a _ n o d u r i = N U L L ;

initializarea acestei variable se face cu valoarea NULL deoarece inainte de inceperea constructiei arborelui lista de noduri ramase este vida. Pentru implementarea mai usoara a functiei de constructie a arborelui se recomanda scrierea unor functii auxiliare si anume:
v o i da c t u a l i z e a z a _ c a r a c t e r ( c h a rc )

Aceasta functie este folosita in etapa de initializare a algoritmului Huffman cand se creeaza lista de noduri terminale si se contorizeaza numarul de aparitii ale fiecarui caracter. Rolul acestei functii este acela de a cauta caracterul primit ca parametru in lista nodurilor terminale existenta pana in acel moment. Daca il gaseste, atunci se va incrementa cimpul , daca nu adauga un nod terminal nou corespunzator caracterului avand campul initializat cu valoarea 1.
n o d* c a u t a _ m i n i m ( )

Aceasta functie este utilizata in etapa de generare a arborelui de codificare. Functia cauta in lista nodurilor ramase, acel nod care are valoarea minima a campului . Procedura elimina din lista acest nod (fara a elibera insa memoria deoarece nodul va fi util in continuare in cadrul arborelui) si intoarce adresa nodului gasit. Pentru testare, se da urmatorul program:
# i n c l u d e # i n c l u d e t y p e d e fs t r u c ts t r _ n o d {c h a r u n s i g n e di n t s t r u c ts t r _ n o d s t r u c ts t r _ n o d
file:///C:/work/UPB/materiale cursuri/SDA/Laborator8/lab8.htm

c a r a c t e r ; n r _ a p a r i t i i ; * s t i n g a ; * d r e a p t a ;
4/6

4/22/13

Laboratorul 8

s t r u c ts t r _ n o d * s u s ; s t r u c ts t r _ n o d * n o d _ u r m a t o r ; } n o d ; n o d * l i s t a _ n o d u r i = N U L L ;

/ /P r o c e d u r ad ea f i s a r el i s t an o d u r ir a m a s e v o i da f i s e a z a _ l i s t a ( v o i d ) { n o d * p ; i f ( l i s t a _ n o d u r i = = N U L L ) { p r i n t f ( " L i s t av i d a . \ n " ) ; r e t u r n ; } p = l i s t a _ n o d u r i ; w h i l e ( p ! = N U L L ) { p r i n t f ( " ( % c , % 2 u ) " , p > c a r a c t e r , p > n r _ a p a r i t i i ) ; p = p > n o d _ u r m a t o r ; } p r i n t f ( " \ n " ) ; } / /P r o c e d u r ad ea f i s a r ea r b o r e v o i da f i s e a z a _ a r b o r e ( n o d* r a d a c i n a , i n tn i v e l ) { i n t i ; i f ( r a d a c i n a = = N U L L ) r e t u r n ; f o r ( i = 0 ; i c a r a c t e r , r a d a c i n a > n r _ a p a r i t i i ) ; a f i s e a z a _ a r b o r e ( r a d a c i n a > s t i n g a , n i v e l + 1 ) ; a f i s e a z a _ a r b o r e ( r a d a c i n a > d r e a p t a , n i v e l + 1 ) ; } / /P r o g r a md et e s t v o i dm a i n ( v o i d ) { c h a r

t e x t [ 1 0 0 ] ;

p r i n t f ( " S i rd ec o d i f i c a t :" ) ; s c a n f ( " % s " , t e x t ) ; g e n e r e a z a _ a r b o r e ( t e x t ) ; }

Se observa prezenta a doua proceduri de afisare care pot fi utilizate in etapa de testare pentru verificarea functionarii functiilor:
v o i da f i s e a z a _ l i s t a ( v o i d )

aceasta procedura afiseaza nodurile existente in lista nodurilor ramase.


v o i da f i s e a z a _ a r b o r e ( n o d* r a d a c i n a , i n tn i v e l )
file:///C:/work/UPB/materiale cursuri/SDA/Laborator8/lab8.htm 5/6

4/22/13

Laboratorul 8

aceasta procedura afiseaza un arbore. Parametrii de apel sunt un pointer catre radacina arborelui si nivelul (adincimea) in arbore de la care se face afisarea (la apel acest parametru trebuie sa fie 0).

file:///C:/work/UPB/materiale cursuri/SDA/Laborator8/lab8.htm

6/6

S-ar putea să vă placă și