83 lines
2.6 KiB
Java
83 lines
2.6 KiB
Java
package questioncomplementaire;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.PriorityQueue;
|
|
|
|
public abstract class Arbre implements Comparable<Arbre> {
|
|
final int frequence;
|
|
|
|
/**
|
|
* @param frequence fréquence cumulée des feuilles de l'arbre
|
|
*/
|
|
public Arbre(int frequence) {
|
|
this.frequence = frequence;
|
|
}
|
|
|
|
/**
|
|
* @param s chaîne encodée dans l'arbre
|
|
* @return un arbre des fréquences d'occurence des lettres de la chaîne
|
|
*/
|
|
public static Arbre buildTree(String s) {
|
|
// tableau de fréquence des caractères
|
|
// indexé par le code du caractère
|
|
// pour simplifier on fait l'hypothèse qu'aucun code n'est supérieur à 256
|
|
int[] frequenceCaracteres = new int[256];
|
|
|
|
// parcourt la chaine génératrice et compte la fréquence de chaque caractère
|
|
for (char c : s.toCharArray())
|
|
frequenceCaracteres[c]++;
|
|
|
|
// liste des éléments
|
|
PriorityQueue<Arbre> lesElements = new PriorityQueue<Arbre>();
|
|
|
|
// au départ on a un ensemble d'arbres réduits chacun à feuille, une pour chaque caractère de la chaine génératrice, non reliés
|
|
//for (int i = 0; i < frequenceCaracteres.length; i++)
|
|
for (int i = 0; i < frequenceCaracteres.length ; i++)
|
|
if (frequenceCaracteres[i] > 0)
|
|
lesElements.offer(new Feuille(frequenceCaracteres[i], (char) i));
|
|
|
|
// on assemble les arbres petit à petit
|
|
// on arrête d'itérer lorsqu'il n'y a plus d'une seule racine
|
|
while (lesElements.size() > 1) {
|
|
// sélectionne les 2 arbres avec la fréquence la plus basse et les retire de la liste
|
|
Arbre a = lesElements.poll();
|
|
Arbre b = lesElements.poll();
|
|
// assemble les 2 arbres retirés et place le nouvel arbre en queue
|
|
lesElements.offer(new Noeud(a, b));
|
|
}
|
|
return lesElements.poll();
|
|
}
|
|
|
|
// établit une relation d'ordre sur les arbres
|
|
public int compareTo(Arbre tree) {
|
|
return frequence - tree.frequence;
|
|
}
|
|
|
|
/**
|
|
* @param prefixe chaîne constituant le préfixe des codes
|
|
* @return la liste des codes de Huffman pour chacune des feuilles de l'arbre
|
|
*/
|
|
public ArrayList<HuffmanCode> collectCodes(StringBuffer prefixe) {
|
|
ArrayList<HuffmanCode> lesCodes = new ArrayList<HuffmanCode>();
|
|
|
|
if (this instanceof Feuille) {
|
|
Feuille leaf = (Feuille) this;
|
|
lesCodes.add(new HuffmanCode(leaf.lettre, prefixe.toString()));
|
|
|
|
} else if (this instanceof Noeud) {
|
|
Noeud node = (Noeud) this;
|
|
|
|
// traverse le fils gauche
|
|
prefixe.append('0');
|
|
lesCodes.addAll(node.filsGauche.collectCodes(prefixe));
|
|
prefixe.deleteCharAt(prefixe.length() - 1);
|
|
|
|
// traverse le fils droit
|
|
prefixe.append('1');
|
|
lesCodes.addAll(node.filsDroit.collectCodes(prefixe));
|
|
prefixe.deleteCharAt(prefixe.length() - 1);
|
|
}
|
|
return lesCodes;
|
|
}
|
|
}
|