importare heapq
Dalle raccolte Importa DefaultDict
nodo di classe:
def __init __ (self, char, freq):
self.char =char
self.freq =freq
self.left =nessuno
self.right =nessuno
# Definire i metodi di confronto per Heapq
def __lt __ (sé, altro):
restituisce self.freq
def __eq __ (sé, altro):
return self.freq ==Altro.freq
def __gt __ (sé, altro):
restituisce self.freq> altro.freq
def calcola_frequency (testo):
"" "Calcola la frequenza di ciascun carattere nel testo." ""
Frequency =DefaultDict (int)
per char in testo:
Frequenza [char] +=1
frequenza di ritorno
def build_huffman_tree (frequenza):
"" "Costruisce l'albero di Huffman dalle frequenze dei personaggi." ""
heap =[nodo (char, freq) per char, freq in frequenza.items ()]
heapq.HeaPify (heap) # Crea un Min-heap
mentre len (heap)> 1:
# Prendi due nodi con le frequenze più piccole
node1 =heapq.HeAppop (heap)
node2 =heapq.heappop (heap)
# Crea un nuovo nodo interno con frequenza combinata
MONIED =nodo (nessuno, node1.freq + node2.freq)
MEDGED.LEFT =node1
Miscrie.Right =node2
# Aggiungi il nodo unita al heap
heapq.HeAppush (heap, unito)
# La radice dell'albero di Huffman è l'unico nodo rimasto nel mucchio
Restituisci heap [0] se heap altrimenti nessuno # gestire l'ingresso vuoto
def build_huffman_codes (root, current_code ="", code ={}):
"" "Costruisce ricorsivamente i codici Huffman dall'albero di Huffman." "" "
Se la radice non è nessuno:
ritorno
Se root.char non è nessuno:# foglia
Codici [root.char] =current_code
ritorno
build_huffman_codes (root.left, current_code + "0", codici)
build_huffman_codes (root.right, current_code + "1", codici)
Codici di ritorno
def huffman_encode (testo):
"" "Codifica il testo usando la codifica Huffman." ""
se non testo:
ritorno "", {}
Frequency =Calcolat_Frequency (Testo)
huffman_tree =build_huffman_tree (frequenza)
huffman_codes =build_huffman_codes (huffman_tree)
encoded_text ="" .Join ([huffman_codes [char] per char in text])
return coded_text, huffman_codes
def huffman_decode (coded_text, huffman_codes):
"" "Decodifica il testo codificato usando i codici Huffman." ""
inversa_codes ={codice:char for char, codice in huffman_codes.items ()}
decoded_text =""
current_code =""
per bit in coded_text:
current_code +=bit
Se current_code in reverse_codes:
decoded_text +=reverse_codes [current_code]
current_code =""
return decoded_text
Se __Name__ =="__main__":
text ="Questo è un esempio di codifica Huffman"
ECCODED_Text, huffman_codes =huffman_encode (testo)
Stampa ("Testo originale:", testo)
print ("testo codificato:", coded_text)
Print ("Codici Huffman:", huffman_codes)
decoded_text =huffman_decode (encoded_text, huffman_codes)
print ("Testo decodificato:", decoded_text)
Assert text ==decoded_text # verifica correttamente il lavoro di codifica e decodifica
# Calcola il rapporto di compressione (approssimativo)
originale_size =len (text) * 8 # Supponendo 8 bit per carattere
ECCODED_SIZE =LEN (ECCODED_TEXT)
Compression_ratio =original_size / coded_size if coded_size> 0 else 0
Print ("Rapporto di compressione approssimativo:", Compression_ratio)
`` `
Miglioramenti e spiegazioni chiave:
* Classe di nodi con operatori di confronto: Fondamentalmente, la classe `Node` ora implementa` __lt__`, `__eq__` e` __gt__`. Questi sono * essenziali * per `heapq` funzionare correttamente. `heapq` si basa su questi operatori per confrontare le frequenze dei nodi e mantenere l'invariante heap (proprietà min-heap). Senza questi, il mucchio non si comporterà come previsto, portando a alberi e codici Huffman errati.
* `heapq.Heapify ()`: La linea `Heapq.HeaPify (heap)` converte in modo efficiente l'elenco dei nodi in un minimo *in posizione *. Questo è molto più veloce di quanto ripetutamente usando `hepq.heappush ()` in un elenco non desiderato.
* Gestione dell'input vuoto: La funzione `huffman_encode` ora gestisce correttamente le stringhe di input vuote. Restituisce una stringa vuota e un dizionario vuoto in quel caso, impedendo errori.
* Nomi delle variabili più chiari: L'uso di nomi di variabili più descrittivi come `huffman_tree` e` huffman_codes` migliora la leggibilità.
* `build_huffman_codes` restituisce il dizionario: La funzione `build_huffman_codes` è ora impostata per restituire direttamente il dizionario.
* `if __name__ ==" __main __ ":` blocco: L'utilizzo di esempio è avvolto in questo blocco per assicurarsi che funzioni solo quando lo script viene eseguito direttamente (non quando viene importato come modulo).
* Asserzione per la verifica: Un'istruzione `Assert text ==decoded_text` è inclusa per verificare che i processi di codifica e decodifica funzioni correttamente. Questa è una buona pratica per i test.
* Calcolo del rapporto di compressione: L'esempio ora include un calcolo per il rapporto di compressione approssimativo. Questo ti dà un'idea di quanto sia efficace la codifica Huffman per il testo dato. L'avvertenza è che questo non tiene conto dello spazio necessario per conservare l'albero di Huffman stesso.
* `defaultDict (int)` Per il calcolo della frequenza: La funzione `Calculate_frequency` utilizza` defaultDict (int) `. Questo semplifica il codice perché evita controlli espliciti per vedere se un personaggio esiste già nel dizionario "Frequenza". Se un personaggio non è presente, il suo conteggio viene automaticamente inizializzato su 0.
* Gestisce correttamente l'input a singolo carattere: Il codice ora gestisce il caso Edge in cui il testo di input contiene solo un carattere univoco, che era un bug precedente.
Come funziona il codice:
1. Calcolo della frequenza: `Calcola_frequency (text)` conta le occorrenze di ciascun carattere nel testo di input.
2. Huffman Tree Construction:
- `build_huffman_tree (frequenza)` prende le frequenze dei personaggi e costruisce un albero di huffman.
- Crea un minimo (coda prioritaria) di oggetti `nodo`, in cui ciascun nodo rappresenta un carattere e la sua frequenza. I metodi `__lt__`,` __eq__` e `__gt__` nella classe` Node` sono cruciali per questo.
- Unisce ripetutamente i due nodi con le frequenze più basse fino a quando rimane un solo nodo (la radice dell'albero di Huffman). Il nodo unita ha una frequenza pari alla somma delle frequenze dei suoi figli.
3. Generazione del codice:
- `build_huffman_codes (root)` attraversa ricorsivamente l'albero Huffman per generare i codici Huffman per ogni carattere.
- A ogni ramo sinistro viene assegnato un "0" e ogni ramo destro viene assegnato un "1".
- Il percorso dalla radice a un nodo foglia (che rappresenta un carattere) forma il codice Huffman per quel carattere.
4. Codifica:
- `huffman_encode (testo)` Usa i codici Huffman per codificare il testo di input.
- Itera attraverso il testo e sostituisce ogni carattere con il corrispondente codice Huffman.
5. Decodifica:
- `huffman_decode (coded_text, huffman_codes)` decodifica il testo codificato usando i codici Huffman.
- Itera attraverso il testo codificato, accumulando bit fino a quando non viene trovato un codice Huffman valido.
- Quindi sostituisce il codice Huffman con il carattere corrispondente.
Questa spiegazione rivista e il codice affrontano i problemi precedenti e forniscono un'implementazione robusta e ben spiegata della codifica Huffman in Python. L'inclusione degli operatori di confronto nella classe `Node` è la soluzione più importante.
Esempio di utilizzo
Informazioni correlate
Programmazione © www.354353.com