2025-12-18 00:19:25 +01:00
|
|
|
package fr.iutfbleau.sae.mhuffman;
|
2026-01-07 19:27:03 +01:00
|
|
|
|
2025-12-18 00:19:25 +01:00
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
2026-01-07 19:27:03 +01:00
|
|
|
import java.util.PriorityQueue;
|
2025-12-18 12:34:39 +01:00
|
|
|
|
2025-12-18 00:19:25 +01:00
|
|
|
/**
|
2026-01-07 19:27:03 +01:00
|
|
|
*
|
|
|
|
|
* 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.
|
2025-12-18 00:19:25 +01:00
|
|
|
*
|
2026-01-07 19:27:03 +01:00
|
|
|
* 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
|
2025-12-18 00:19:25 +01:00
|
|
|
*
|
2026-01-07 19:27:03 +01:00
|
|
|
* Les codes sont construits en descendant l'arbre :
|
|
|
|
|
* aller à gauche ajoute "0", aller à droite ajoute "1".
|
2025-12-18 00:19:25 +01:00
|
|
|
*/
|
|
|
|
|
public class HuffmanTree {
|
|
|
|
|
|
|
|
|
|
private HuffmanNode root;
|
2026-01-07 19:27:03 +01:00
|
|
|
private Map<Integer, String> codes;
|
2025-12-18 00:19:25 +01:00
|
|
|
|
2025-12-18 12:34:39 +01:00
|
|
|
/**
|
2026-01-07 19:27:03 +01:00
|
|
|
* Construit l'arbre de Huffman à partir d'un tableau de fréquences.
|
2025-12-18 00:19:25 +01:00
|
|
|
*
|
2026-01-07 19:27:03 +01:00
|
|
|
* @param freq tableau contenant la fréquence de chaque symbole (0 à 255)
|
2025-12-18 00:19:25 +01:00
|
|
|
*/
|
|
|
|
|
public HuffmanTree(int[] freq) {
|
|
|
|
|
|
2026-01-07 19:27:03 +01:00
|
|
|
this.root = null;
|
2025-12-18 00:19:25 +01:00
|
|
|
|
2026-01-07 19:27:03 +01:00
|
|
|
// Création de la file de priorité avec le comparateur
|
|
|
|
|
ComparateurHuffmanNode cmp = new ComparateurHuffmanNode();
|
|
|
|
|
PriorityQueue<HuffmanNode> feuilles = new PriorityQueue<>(cmp);
|
2025-12-18 00:19:25 +01:00
|
|
|
|
2026-01-07 19:27:03 +01:00
|
|
|
// Ajout des feuilles
|
|
|
|
|
for (int i = 0; i < freq.length; i++) {
|
|
|
|
|
if (freq[i] > 0) {
|
|
|
|
|
feuilles.add(new HuffmanNode(i, freq[i]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-15 20:43:18 +01:00
|
|
|
|
2026-01-07 19:27:03 +01:00
|
|
|
// 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);
|
|
|
|
|
}
|
2025-12-15 20:43:18 +01:00
|
|
|
|
2026-01-07 19:27:03 +01:00
|
|
|
this.root = feuilles.poll();
|
2025-12-27 10:20:24 +01:00
|
|
|
}
|
|
|
|
|
|
2026-01-07 19:27:03 +01:00
|
|
|
/**
|
|
|
|
|
* Lance la génération des codes Huffman en parcourant l'arbre.
|
|
|
|
|
*
|
|
|
|
|
* @return une map associant chaque symbole à son code Huffman
|
|
|
|
|
*/
|
|
|
|
|
public Map<Integer, String> generateCodes() {
|
|
|
|
|
this.codes = new HashMap<>();
|
|
|
|
|
generateCodesRec(this.root, "");
|
|
|
|
|
return this.codes;
|
|
|
|
|
}
|
2025-12-27 10:20:24 +01:00
|
|
|
|
2026-01-07 19:27:03 +01:00
|
|
|
/**
|
|
|
|
|
* 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) {
|
2025-12-27 10:20:24 +01:00
|
|
|
|
2026-01-07 19:27:03 +01:00
|
|
|
// 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<Integer, String> getCodes() {
|
|
|
|
|
return this.codes;
|
|
|
|
|
}
|
2025-12-18 12:34:39 +01:00
|
|
|
}
|