Код Хаффмана на Java.

Задача: Предположив, что имеется текст, содержащий p1 символов c1, p2 символов c2 и т.д., постройте код Хаффмана и найдите суммарное число битов, необходимое для кодирования такого текста.

Huffman.java (Содержит главный класс)

package huffman;

import java.io.*;
import java.util.*;

public class Huffman {

     public static void main(String[] args) throws FileNotFoundException, IOException {
          int n;
          Map frequenceMap = new HashMap<>(); // символ-частота
          Map freeMap = new HashMap<>(); // символ-свобод./занят
          Map parentMap = new HashMap<>(); // символ-код
          Scanner input = new Scanner(new File("src/huffman/huffman.in.txt"));
          n = input.nextInt();
          for (int i = 0; i < n; i++) {
               frequenceMap.put("c" + (i + 1), input.nextInt());
               freeMap.put("c" + (i + 1), true);
               parentMap.put("c" + (i + 1), "");
          }
          input.close();
          Tree t = new Tree(frequenceMap, freeMap, parentMap);
     }
}

Tree.java

package huffman;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

public final class Tree {

     private String firstMin, secondMin;
     private int firstMinValue, secondMinValue, trueCount, codeLength = 0;
     private Map frequence;
     private Map free;
     private Map parent;

     Tree(Map fq, Map f, Map p) throws FileNotFoundException, IOException {
          frequence = fq;
          free = f;
          parent = p;
          trueCount = frequence.size();
          buildTree(fq, f);
          showTree();
     }

     public void showTree() throws FileNotFoundException, IOException {
          for (String key : parent.keySet()) {
               codeLength += parent.get(key).length() * frequence.get(key);
          }
          FileOutputStream output = new FileOutputStream("src/huffman/huffman.out.txt");
          output.write((codeLength+"").getBytes());
          output.close();
     }

     public void buildTree(Map fq, Map f) {
          while (trueCount != 1) {
               min(fq, f);
               fq.put(firstMin + secondMin, firstMinValue + secondMinValue);
               f.put(firstMin + secondMin, true);
               f.put(firstMin, false);
               f.put(secondMin, false);
               trueCount--;
               for (String key : parent.keySet()) {
                    if (firstMin.contains(key)) {
                         parent.put(key, "0" + parent.get(key));
                    } else if ((secondMin != null) && (secondMin.contains(key))) {
                         parent.put(key, "1" + parent.get(key));
                    }
               }
          }
     }

     private void min(Map fq, Map f) {
          firstMin = null;
          secondMin = null;
          int min = 1000000001;
          for (String key : fq.keySet()) {
               if ((fq.get(key) < min) && (f.get(key) == true)) {
                    min = fq.get(key);
                    firstMin = key;
                    firstMinValue = min;
               }
          }
          min = 1000000001;
          for (String key : fq.keySet()) {
               if ((fq.get(key) < min) && (!key.equals(firstMin) && (f.get(key) == true))) {
                    min = fq.get(key);
                    secondMin = key;
                    secondMinValue = min;
               }
          }
     }
}