La codifica di Huffman Un'implementazione in C++ (parte del materiale è opera di Mark Nelson, Dr. Dobb’s Journal, Gennaio 1996)
Perché C++ Nessuna ragione particolare, andavano benissimo anche il C, il Java e molti altri Il vantaggio principale dell'uso del C++ è di poter utilizzare la STL (Standard Template Library)
Cos'è la STL E' una libreria di templates Un template è una classe che ha un tipo di dato parametrico (per inciso, questo tipo di dato può essere un tipo di dato primitivo, o una classe a sua volta) vector, queue
Coda FIFO Operazioni: push(), pop() Molto semplice da implementare, ma talvolta avremmo bisogno di qualcosa di un po' più sofisticato
Coda con priorità In una coda con priorità ogni elemento ha una priorità I nuovi elementi vengono aggiunti con la funzione push() Con la funzione pop() si estrae un elemento dalla coda. In un coda con priorità questo elemento non è il più vecchio ma quello con priorità massima Questo può essere utile in certi tipi di task, ad esempio nello scheduler di un sistema operativo
Coda con priorità
Implementazione con uno heap Una possibile implementazione efficiente di una coda con priorità si serve di uno heap Uno heap è una struttura dati che tiene gli elementi della coda in uno stato parzialmente ordinato. Inserzione ed estrazione costano log(N) in tempo, dove N è il numero di elementi nella coda Anche l'overhead di memoria è praticamente nullo
Heap Gli elementi di uno heap sono memorizzati in un array contiguo (diciamo, per comodità, dalla posizione 1 alla posizione N) Gli elementi nell'array fanno parte di un albero binario implicito. Ogni elemento x (eccetto il nodo radice) ha il padre in x/2 (intero inferiore) Ogni nodo ha una priorità che è maggiore o uguale a quella di entrambi i suoi figli
Heap
Heap: push() swap
Heap: pop() Qualcosa di simile accade quando si esegue la funzione pop()...
STL priority_queue Implementa una coda con priorità con uno heap Non abbiamo bisogno di ricordare tutti i dettagli dello heap e della ristrutturazione dell'albero implicito perché... è tutto automatico!
Huffman: implementazione - I Class node { public: int weight; unsigned char value; const node *child0; const node *child1;
Huffman: implementazione - II node(unsigned char c=0, int i=-1) { value=c; weight=i; child0=0; child1=0; } node(const node *c0, const node *c1) { value=0; weight=c0->weight + c1->weight; child0=c0; child1=c1; } Costruttori
Huffman: implementazione - III Operatore di confronto bool operator>(const node &a) const { return weight > a.weight; }
Il ciclo fondamentale while (q.size()>1) { node *child0 = new node(q.top()); q.pop(); node *child1 = new node(q.top()); q.pop(); q.push(node(child0, child1)); } e ora, diamo un'occhiata ai risultati...
Implementare una versione che accetti un qualunque file di testo Calcolare L(X), H(X) Realizzare la stessa implementazione in Java o in C. Quale è più difficile? Aggiungere il controllo del tempo di elaborazione Compiti per casa