package fr.iutfbleau.sae.mhuffman; import java.util.HashMap; import java.util.Map; import java.util.PriorityQueue; /** * * Cette classe construit un arbre de Huffman à partir d'un tableau * de fréquences. Une fois l'arbre construit, elle permet aussi de * générer les codes Huffman associés à chaque symbole. * * Le principe est le suivant : * - chaque symbole non nul devient une feuille avec sa fréquence * - on fusionne toujours les deux plus petites fréquences * - on obtient une racine unique * - un parcours de l'arbre permet ensuite de fabriquer les codes * * Les codes sont construits en descendant l'arbre : * aller à gauche ajoute "0", aller à droite ajoute "1". */ public class HuffmanTree { private HuffmanNode root; private Map codes; /** * Construit l'arbre de Huffman à partir d'un tableau de fréquences. * * @param freq tableau contenant la fréquence de chaque symbole (0 à 255) */ public HuffmanTree(int[] freq) { this.root = null; // Création de la file de priorité avec le comparateur ComparateurHuffmanNode cmp = new ComparateurHuffmanNode(); PriorityQueue feuilles = new PriorityQueue<>(cmp); // Ajout des feuilles for (int i = 0; i < freq.length; i++) { if (freq[i] > 0) { feuilles.add(new HuffmanNode(i, freq[i])); } } // Fusion des nœuds (feuille) jusqu'à obtenir la racine while (feuilles.size() > 1) { HuffmanNode left = feuilles.poll(); HuffmanNode right = feuilles.poll(); HuffmanNode parent = new HuffmanNode(left, right); feuilles.add(parent); } this.root = feuilles.poll(); } /** * Lance la génération des codes Huffman en parcourant l'arbre. * * @return une map associant chaque symbole à son code Huffman */ public Map generateCodes() { this.codes = new HashMap<>(); generateCodesRec(this.root, ""); return this.codes; } /** * Méthode récursive qui construit les codes Huffman. * * @param node nœud courant * @param prefixe code accumulé (suite de 0 et de 1) */ private void generateCodesRec(HuffmanNode node, String prefixe) { // Cas feuille : on ajoute le code if (node.isLeaf()) { if (prefixe.length() > 0) { this.codes.put(node.getValue(), prefixe); } else { // Cas spécial : un seul symbole dans l'arbre this.codes.put(node.getValue(), "0"); } return; } // Descendre à gauche s generateCodesRec(node.getLeft(), prefixe + "0"); // Descendre à droite generateCodesRec(node.getRight(), prefixe + "1"); } /** * Permet de récupérer la racine de l'arbre. * * @return la racine de l'arbre de Huffman */ public HuffmanNode getRoot() { return this.root; } /** * Retourne les codes Huffman générés. * * @return une map symbole code */ public Map getCodes() { return this.codes; } }