Innanzitutto, come discusso nei commenti, dovresti sbarazzarti delle frequenze poiché hai solo bisogno di loro per creare l'albero, non per riprodurre i codici per la decodifica. Nel tuo programma, ma non sul disco, la struttura ad albero potrebbe apparire come questa (notare l'assenza di frequenze):
struct Node {
char value; // only used for leaf nodes
// leaf nodes have BOTH child pointers NULL
struct Node *left, *right;
}
Penso che il seguente schema dovrebbe permettere di riprodurre l'albero (sebbene non le frequenze) usando al massimo 2n * k bit per alfabeti in cui ogni carattere prende k bit (quindi k < = log2 n < = k + 1):
- Assegna indici consecutivi arbitrari a tutti i nodi interni dell'albero di Huffman.
- Per ogni carattere, scrivi l'indice del nodo genitore.
- Ordina i nodi interni secondo i loro indici. Per ogni nodo tranne la radice, scrivi l'indice del suo nodo genitore. Per il nodo radice, rendi il suo indice "genitore" uguale a stesso .
Dato che ci sono al massimo n-1 nodi interni, gli indici dei nodi si adattano ciascuno a k bit. Quindi i record del nodo interno più i record di caratteri, arriviamo a poco meno di 2n * k bit. La decodifica è relativamente semplice: prima leggi i record di carattere k, crea i nodi interni corrispondenti e aggiungi iterativamente i nodi scoperti di recente (quelli referenziati da altri nodi interni ma non ancora creati). È possibile riconoscere il nodo radice tramite il riferimento automatico.
Si noti che ciò richiederebbe una diversa struttura ad albero, una con riferimenti padre invece di riferimenti figlio e un flag per distinguere i nodi foglia (in memoria, è possibile utilizzare NULL per% root% co_de) Se questo rende più facile generare i codici, puoi invertire i puntatori genitore, cioè trasformare questa rappresentazione nella bella struttura top-down sopra menzionata.
Avvertenza: presumo che k sia noto a entrambe le parti (in caso contrario, un singolo byte in più dovrebbe essere sufficiente per qualsiasi applicazione pratica). Presumo anche un alfabeto di vettori bit a dimensione fissa, ma penso che sia il caso in quasi tutte le applicazioni (e se non è vero, è possibile aggiungere i metadati e andarsene via piuttosto bene).