Esercizio - codice di Huffman con frequenze in progressione geometrica, trie e codeword (compito del 29 gennaio 2026, es. 2)
In questa pagina 4
Testo (compito d'esame di Algoritmi per l'Ingegneria, Ing. Informatica UniPD, 29 gennaio 2026, seconda parte, esercizio 2, 16 punti; nel testo originale i due punti sono numerati 1.(a) e 1.(b)). Si consideri un file definito su un alfabeto di caratteri e si supponga che, per , il carattere abbia frequenza
(a) [6 punti] Si disegni il trie associato alla codifica di Huffman di per e si elenchino le quattro parole di codice per i caratteri .
(b) [10 punti] Per il caso di generico, si determini la forma del trie e la codeword associata al generico carattere , per . Le risposte vanno giustificate formalmente.
Attenzione: nello svolgimento ci si attenga alle convenzioni sul trie adottate nel testo e a lezione: il figlio sinistro ha frequenza non superiore a quella del figlio destro; il lato che congiunge un nodo al figlio sinistro ha etichetta 0 e quello che lo congiunge al figlio destro etichetta 1.
Prima di cominciare: le frequenze sono ammissibili
Le sono positive e per la somma di una progressione geometrica (SommatorieIl simbolo di sommatoria, le sue proprietà (linearità, additività, cambio di indice) e le somme notevoli di Gauss e geometrica.Sommatorie →). Ogni frequenza è il doppio della precedente: . È la proprietà che governa tutto l'esercizio.
Punto (a):
Qui e
Si indica con la foglia del carattere e si esegue HUFFMAN (Codifica di Huffman - codici prefissi, algoritmo e ottimalitàCompressione con codifica per carattere: la lunghezza variabile risparmia bit ma deve essere iniettiva, e i codici prefissi lo garantiscono; un codice prefisso è un trie binario con una foglia per carattere, di costo B(T) = somma di f(c) d_T(c), e quello ottimo è un albero pieno con n-1 nodi interni. L'algoritmo di Huffman fonde ripetutamente i due alberi di frequenza minima usando una coda con priorità (2n-1 estrazioni, costo O(n log n)); l'ottimalità si prova con la scelta greedy (i due caratteri più rari sono foglie sorelle di profondità massima, per scambio) e la sottostruttura (B(T) = B(T') + f(x) + f(y)). Esempio completo con 6 caratteri, B = 2,24.Codifica di Huffman - codici prefissi, algoritmo e ottimalità →): iterazioni, ciascuna fonde i due nodi di frequenza minima, con il più leggero a sinistra.
| iterazione | coda prima | estratti (sx, dx) | nodo creato | coda dopo |
|---|---|---|---|---|
| 1 | di peso | |||
| 2 | (quella sopra) | () | di peso | |
| 3 | (quella sopra) | () | di peso |
Il trie (i pesi sono in quindicesimi, 0 a sinistra e 1 a destra):
(15)
0/ \1
(7) c4: 8
0/ \1
(3) c3: 4
0/ \1
c1: 1 c2: 2Parole di codice: , , , . Costo (lunghezza media): Controllo con la somma dei pesi dei nodi interni: . Il codice a lunghezza fissa ne userebbe .
Nota sulla soluzione del corso: riporta , ma ; l'approssimazione è un errore di stampa (la frazione è giusta).
Punto (b): generico
Passo 1: ogni frequenza supera la somma di tutte le precedenti. Per , La disuguaglianza è stretta, quindi non ci sono mai pareggi nelle scelte dell'algoritmo, e il trie è univocamente determinato.
Passo 2: lo svolgimento di Huffman. Si indica con il nodo che ha per foglie (con ) e con il suo peso.
Affermazione. Per , all'inizio dell'iterazione la coda contiene esattamente i nodi . L'iterazione estrae per primo (diventa il figlio sinistro), poi (figlio destro), e crea di peso .
Dimostrazione per induzione su .
- : la coda contiene le foglie con pesi (la sequenza è strettamente crescente): i due minimi sono e , estratti in questo ordine; nasce con peso .
- Passo (con ): alla fine dell'iterazione la coda contiene (i nodi e sono stati sostituiti da ). All'inizio dell'iterazione i pesi sono e . Per con al posto di vale , quindi il minimo è e il secondo minimo è , senza pareggi. Si fondono nell'ordine (sinistro, destro) , con peso .
Dopo l'iterazione resta il solo , di peso (controllo), la radice. Il confronto di sinistra e destra rispetta la convenzione del testo, perché il figlio sinistro è sempre quello di frequenza minore.
Passo 3: la forma del trie. I nodi interni sono ( nodi, come deve essere per un albero pieno con foglie) e il figlio sinistro di è , il destro è la foglia . Quindi il trie è una catena sinistra: un unico cammino dalla radice alla foglia più a sinistra che passa per , in cui ogni nodo interno ha come figlio destro una foglia: sotto la radice, sotto , ..., sotto .
radice z_{1..n} --0--> z_{1..n-1} --0--> ... --0--> z_{1..2} --0--> c_1
|1 |1 |1
c_n c_{n-1} c_2Passo 4: le parole di codice. Il nodo sta a profondità (la radice a profondità , e ogni passo verso sinistra scende di un livello), e il suo cammino dalla radice è . Allora:
- per la foglia è il figlio destro di (a profondità ): la parola è seguita da , lunga ;
- la foglia è il figlio sinistro di (a profondità ): la parola è , lunga .
Per : , , , , come nel punto (a). In particolare il carattere più frequente ha una parola di un solo bit, e le lunghezze sono per , cioè la parola si accorcia di un bit ogni volta che la frequenza raddoppia.
Costo. Con la somma dei pesi dei nodi interni, per : Per : , come nel punto (a). Per tende a bit per carattere, anche se il cammino più lungo ha bit.
Ottimalità. Il trie ottenuto è quello ritornato da HUFFMAN, quindi è ottimo per il teorema di correttezza dell'algoritmo; la forma a catena è l'unica possibile con questo input perché le scelte sono forzate dalle disuguaglianze strette.
Verifica
Con Python (HUFFMAN con heapq e frazioni esatte) per ogni da a : le parole sono esattamente e , il figlio sinistro ha sempre frequenza del destro, e il costo è , uguale alla somma dei pesi dei nodi interni; per vengono e .
Versione ripasso
- Dati: per ; e (SommatorieIl simbolo di sommatoria, le sue proprietà (linearità, additività, cambio di indice) e le somme notevoli di Gauss e geometrica.Sommatorie →). Convenzioni: il figlio sinistro ha frequenza del destro;
0a sinistra e1a destra. Richieste: (a) trie e parole per (6 punti); (b) forma del trie e parola di per generico, con giustificazione formale (10 punti). - (a) : frequenze . Fusioni: di peso ; () con () dà di peso ; con () dà la radice . Parole , , , . (il corso scrive , errore di stampa); controllo con i nodi interni . Algoritmo e convenzioni in Codifica di Huffman - codici prefissi, algoritmo e ottimalitàCompressione con codifica per carattere: la lunghezza variabile risparmia bit ma deve essere iniettiva, e i codici prefissi lo garantiscono; un codice prefisso è un trie binario con una foglia per carattere, di costo B(T) = somma di f(c) d_T(c), e quello ottimo è un albero pieno con n-1 nodi interni. L'algoritmo di Huffman fonde ripetutamente i due alberi di frequenza minima usando una coda con priorità (2n-1 estrazioni, costo O(n log n)); l'ottimalità si prova con la scelta greedy (i due caratteri più rari sono foglie sorelle di profondità massima, per scambio) e la sottostruttura (B(T) = B(T') + f(x) + f(y)). Esempio completo con 6 caratteri, B = 2,24.Codifica di Huffman - codici prefissi, algoritmo e ottimalità →.
- (b) Chiave: per , , disuguaglianza stretta: nessun pareggio, il trie è univocamente determinato.
- Affermazione (induzione su ): all'inizio dell'iterazione la coda contiene ; l'iterazione estrae (sinistro) e (destro) e crea di peso . Base : , i minimi sono e . Passo: per la chiave sopra.
- Forma del trie: catena sinistra con nodi interni ; il figlio sinistro di è e il destro è la foglia ; la foglia più a sinistra è .
- Parole: è a profondità con cammino ; () è figlio destro di , quindi (lunghezza ); è figlio sinistro di (profondità ), quindi . Per si ritrova : la parola si accorcia di un bit ogni volta che la frequenza raddoppia.
- Costo: somma dei pesi dei nodi interni, ; per vale . Il trie è ottimo perché è quello di HUFFMAN.
- Verifica: con Python per parole, convenzione sinistra/destra e costo coincidono con le formule.
- Errori tipici: scambiare destra e sinistra (il più leggero, , va a sinistra); scrivere anche per invece di ; dimenticare di motivare l'assenza di pareggi con la disuguaglianza stretta; contare nodi interni invece di ; dare la forma per generico senza induzione.