Fini tree node et frequency table
This commit is contained in:
@@ -51,11 +51,14 @@ package mhuffman {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class HuffmanNode #aliceblue {
|
class HuffmanNode #aliceblue {
|
||||||
+ value : int
|
- value : int
|
||||||
+ frequency : int
|
- frequency : int
|
||||||
+ left : HuffmanNode
|
- left : HuffmanNode
|
||||||
+ right : HuffmanNode
|
- right : HuffmanNode
|
||||||
+ isLeaf()
|
+ setLeft(HuffmanNode lef): void
|
||||||
|
+ setRight(HuffmanNode rig): void
|
||||||
|
+ isLead(HuffmanNode f): boolean
|
||||||
|
+ getFrequence(): int
|
||||||
}
|
}
|
||||||
|
|
||||||
class HuffmanTree #aliceblue {
|
class HuffmanTree #aliceblue {
|
||||||
|
|||||||
@@ -1,40 +1,117 @@
|
|||||||
public class HuffmanNode{
|
/**
|
||||||
private char value;
|
* Représente un nœud de l'arbre de Huffman.
|
||||||
private int frequence;
|
* <p>
|
||||||
|
* Un {@code HuffmanNode} peut être :
|
||||||
|
* <ul>
|
||||||
|
* <li>une feuille, contenant une valeur (symbole) et une fréquence</li>
|
||||||
|
* <li>un nœud interne, contenant uniquement une fréquence et deux enfants</li>
|
||||||
|
* </ul>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Cette classe est une structure de données utilisée par {@code HuffmanTree}
|
||||||
|
* pour construire l'arbre de Huffman.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Algassimou Pellel Diallo
|
||||||
|
* @version 1.1
|
||||||
|
* @since 2025-12-17
|
||||||
|
*/
|
||||||
|
public class HuffmanNode {
|
||||||
|
|
||||||
private HuffmanNode left;
|
/** Valeur de la composante (cette valeur est appelée symbole, voir l'histoire de huffman, tres interressant) représentée par ce nœud (si feuille). c'est la part de la composante (rouge, verte ou bleue) dans la couleur d'un pixel. */
|
||||||
private HuffmanNode right;
|
private int value;
|
||||||
|
|
||||||
|
/** Fréquence du symbole (somme des fréquences des enfants). */
|
||||||
|
private int frequence;
|
||||||
|
|
||||||
|
/** Fils gauche du nœud (null si feuille). */
|
||||||
|
private HuffmanNode left;
|
||||||
|
|
||||||
public HuffmanNode(char v,int f){
|
/** Fils droit du nœud (null si feuille). */
|
||||||
this.value = v;
|
private HuffmanNode right;
|
||||||
this.frequence = f;
|
|
||||||
this.right = null;
|
|
||||||
this.left = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construit un nœud feuille de Huffman.
|
||||||
|
* <p>
|
||||||
|
* Ce constructeur est utilisé pour représenter une valeur
|
||||||
|
* issue de la table de fréquences.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param value la valeur (symbole) représentée par ce nœud
|
||||||
|
* @param frequence la fréquence d'apparition de la valeur
|
||||||
|
*/
|
||||||
|
public HuffmanNode(int value, int frequence) {
|
||||||
|
this.value = value;
|
||||||
|
this.frequence = frequence;
|
||||||
|
this.left = null;
|
||||||
|
this.right = null;
|
||||||
|
}
|
||||||
|
|
||||||
public void setSonLeft(HuffmanNode lef){
|
/**
|
||||||
this.left = lef;
|
* Construit un nœud interne de Huffman.
|
||||||
}
|
* <p>
|
||||||
|
* Ce constructeur est utilisé lors de la fusion de deux nœuds
|
||||||
|
* de plus faible fréquence lors de la construction de l'arbre.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param left le fils gauche
|
||||||
|
* @param right le fils droit
|
||||||
|
*/
|
||||||
|
public HuffmanNode(HuffmanNode left, HuffmanNode right) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
this.frequence = left.frequence + right.frequence;
|
||||||
|
}
|
||||||
|
|
||||||
public void setSonRight(HuffmanNode rig){
|
/**
|
||||||
this.right = rig;
|
* Indique si ce nœud est une feuille.
|
||||||
}
|
*
|
||||||
|
* @return {@code true} si le nœud est une feuille, {@code false} sinon
|
||||||
|
*/
|
||||||
|
public boolean isLeaf() {
|
||||||
|
return this.left == null && this.right == null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isLead(HuffmanNode f){
|
/**
|
||||||
// on est une feuille si on a pas de fils gauche et ni de fils droit !
|
* Retourne la fréquence du nœud.
|
||||||
boolean b = true;
|
*
|
||||||
|
* @return la fréquence
|
||||||
|
*/
|
||||||
|
public int getFrequence() {
|
||||||
|
return this.frequence;
|
||||||
|
}
|
||||||
|
|
||||||
if(this.left == null && this.right == null){
|
/**
|
||||||
b = true;
|
* Retourne le fils gauche du nœud.
|
||||||
}else{
|
*
|
||||||
b = false;
|
* @return le fils gauche
|
||||||
|
*/
|
||||||
|
public HuffmanNode getLeft() {
|
||||||
|
return this.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le fils droit du nœud.
|
||||||
|
*
|
||||||
|
* @return le fils droit
|
||||||
|
*/
|
||||||
|
public HuffmanNode getRight() {
|
||||||
|
return this.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la valeur représentée par ce nœud.
|
||||||
|
* <p>
|
||||||
|
* Cette méthode n'a de sens que si le nœud est une feuille.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return la valeur du symbole
|
||||||
|
*/
|
||||||
|
public int getValue() {
|
||||||
|
if (!this.isLeaf()) {
|
||||||
|
throw new IllegalStateException("La valeur n'est définie que pour les feuilles.");
|
||||||
}
|
}
|
||||||
|
return this.value;
|
||||||
return b;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ajouter d'autres méthode tel que les getters par exemple !!!
|
|
||||||
}
|
}
|
||||||
@@ -1,36 +1,139 @@
|
|||||||
import java.util.*;
|
package fr.iutfbleau.sae.mhuffman;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implémente un arbre de Huffman utilisé pour la compression de données.
|
||||||
|
* <p>
|
||||||
|
* La classe {@code HuffmanTree} est chargée de représenter la structure
|
||||||
|
* de l'arbre de Huffman et de générer les codes binaires associés aux symboles.
|
||||||
|
* Elle s'appuie sur la classe {@link HuffmanNode} pour représenter les nœuds
|
||||||
|
* de l'arbre.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* L'arbre est construit à partir des fréquences des symboles calculées
|
||||||
|
* en amont (par exemple à l'aide d'une {@code FrequencyTable}).
|
||||||
|
* Chaque symbole est d'abord représenté par une feuille, puis les nœuds
|
||||||
|
* sont combinés progressivement selon l'algorithme de Huffman afin
|
||||||
|
* d'obtenir un arbre binaire optimal.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Une fois l'arbre construit, celui-ci est parcouru afin de générer une
|
||||||
|
* table de correspondance associant à chaque symbole un code binaire unique.
|
||||||
|
* Les symboles les plus fréquents se retrouvent plus proches de la racine
|
||||||
|
* et possèdent donc des codes plus courts, ce qui permet de réduire
|
||||||
|
* la taille des données compressées.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Cette classe ne s'occupe pas de la lecture ou de l'écriture des bits.
|
||||||
|
* Elle fournit uniquement la structure et les informations nécessaires
|
||||||
|
* à la compression, qui sont ensuite exploitées par des flux binaires
|
||||||
|
* dédiés.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Algassimou Pellel Diallo
|
||||||
|
* @version 1.0
|
||||||
|
* @since 2025-12-13
|
||||||
|
*/
|
||||||
|
public class HuffmanTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Racine de l'arbre de Huffman.
|
||||||
|
* <p>
|
||||||
|
* Ce nœud est le résultat final de la construction de l'arbre et constitue
|
||||||
|
* le point de départ pour la génération des codes binaires ainsi que
|
||||||
|
* pour le décodage des données compressées.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
private HuffmanNode root;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construit un arbre de Huffman.
|
||||||
|
* <p>
|
||||||
|
* Le constructeur est responsable de l'initialisation de la structure
|
||||||
|
* de l'arbre. En pratique, il combine les nœuds feuilles représentant
|
||||||
|
* les symboles par ordre croissant de fréquence jusqu'à obtenir un
|
||||||
|
* unique nœud racine.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Les détails de la construction (structure de données utilisée,
|
||||||
|
* ordre des fusions, etc.) sont volontairement séparés de la logique
|
||||||
|
* de génération des codes.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public HuffmanTree(int[] freq) {
|
||||||
|
// J'initialise la racine à null.
|
||||||
|
this.root = null;
|
||||||
|
|
||||||
|
// je cree une collection de feuilles
|
||||||
|
|
||||||
|
/////////////////////////////////// Voir si ya moyen doptimiser //////////////////////////////////////
|
||||||
|
|
||||||
|
List<HuffmanNode> feuilles = new ArrayList<>();
|
||||||
|
|
||||||
|
// pour chaque valeur(symbole) dans la table de frequence
|
||||||
|
for (int i = 0; i < freq.length; i++) {
|
||||||
|
// si la frequence est superieure a 0 , on cree une feuille
|
||||||
|
if (freq[i] > 0) {
|
||||||
|
// pour la valeur (symbole) i avec frequence freq[i], on cree une feuille
|
||||||
|
HuffmanNode feuille = new HuffmanNode(i, freq[i]);
|
||||||
|
// on ajoute la feuille à la collection
|
||||||
|
feuilles.add(feuille);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// On tri les feuilles par frequence croissante jutilie un comparator qui compare la vareur retournee par getFrequence de chaque feuille
|
||||||
|
// Referencement de methode avec ::
|
||||||
|
feuilles.sort(Comparator.comparingInt(HuffmanNode::getFrequence));
|
||||||
|
// flemme de faire un algo de tri alors que java le fait tres bien a voir a la fin si je vais coder une liste chainee avec un tri par insertion personnalise
|
||||||
|
|
||||||
|
|
||||||
public class HuffmanTree{
|
// Fusion des nœuds jusqu'à obtenir la racine
|
||||||
|
// Tant qu'il y a plus d'une feuille dans la collection
|
||||||
|
while (feuilles.size() > 1) {
|
||||||
|
// je prends les deux feuilles de plus faible fréquence
|
||||||
|
HuffmanNode left = feuilles.remove(0);
|
||||||
|
HuffmanNode right = feuilles.remove(0);
|
||||||
|
|
||||||
|
// je crée un nœud interne en les combinant
|
||||||
|
HuffmanNode parent = new HuffmanNode(left, right);
|
||||||
|
|
||||||
private HuffmanNode root;
|
// j'insère le nœud parent dans la collection à la bonne position pour maintenir l'ordre (plus performant qu'un tri complet à chaque itération)
|
||||||
|
int index = 0;
|
||||||
|
// tant que l'index est dans les limites et que la frequence du noeud à l'index est inférieure à celle du parent
|
||||||
|
while (index < feuilles.size()&& feuilles.get(index).getFrequence() < parent.getFrequence()) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
feuilles.add(index, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// a la fin il ne reste qu'un seul noeud : la racine de l'arbre
|
||||||
|
this.root = feuilles.get(0);
|
||||||
public HuffmanTree(){
|
|
||||||
// constructeur : création des feuilles , puis après de l'abre !
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
utilisation de PriorityQueue<E> pour gérer selon la fréquence !!
|
|
||||||
|
|
||||||
|
|
||||||
root sera donc la racine de l'arbre
|
|
||||||
création des branches avec les plus petites fréquence :
|
|
||||||
|
|
||||||
Etape de construction suggérer :
|
|
||||||
|
|
||||||
1 - faire une boucle sur le tableau des fréquences , puis ajouter chaque fréquence > 0 comme un nouveau noeud dans la pile puis empiler
|
|
||||||
|
|
||||||
2- depiler les deux premieres valeurs pour former les branches jusqu'à ce que la pile ne contient un seul elément
|
|
||||||
|
|
||||||
3 - cet élément sera la racine de l'abre
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la racine de l'arbre de Huffman.
|
||||||
|
* <p>
|
||||||
|
* Cette méthode permet d'accéder à la structure complète de l'arbre,
|
||||||
|
* notamment lors de la génération des codes ou du décodage des données.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return le nœud racine de l'arbre de Huffman
|
||||||
|
*/
|
||||||
|
public HuffmanNode getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Map<Integer,String> generateCodes(){
|
public Map<Integer,String> generateCodes(){
|
||||||
// methode recursive : appliquer à chaque branche de l'abre , chaque feuille !!!
|
// methode recursive : appliquer à chaque branche de l'abre , chaque feuille !!!
|
||||||
// 1 - trouver cas de base + comment generer les codes :
|
// 1 - trouver cas de base + comment generer les codes :
|
||||||
|
|||||||
Reference in New Issue
Block a user