glog_td4/questioncomplementaire/Arbre.java
2018-04-01 14:34:28 +02:00

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;
}
}