package questioncomplementaire; import java.util.ArrayList; import java.util.PriorityQueue; public abstract class Arbre implements Comparable { 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 lesElements = new PriorityQueue(); // 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 collectCodes(StringBuffer prefixe) { ArrayList lesCodes = new ArrayList(); 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; } }