diff --git a/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java b/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java
index b2a325e6395ce7004d5d7274eea951870376fc73..ca4dcf7f96406227f58c3a41f7d924d0997be12c 100644
--- a/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java
+++ b/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java
@@ -4,8 +4,8 @@ import cz.it4i.qcmp.cache.QuantizationCacheManager;
 import cz.it4i.qcmp.cache.VQCacheFile;
 import cz.it4i.qcmp.cli.CompressionOptionsCLIParser;
 import cz.it4i.qcmp.cli.CustomFunctionBase;
-import cz.it4i.qcmp.huffman.Huffman;
 import cz.it4i.qcmp.huffman.HuffmanNode;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
 import cz.it4i.qcmp.io.InBitStream;
 import cz.it4i.qcmp.io.OutBitStream;
 import cz.it4i.qcmp.quantization.vector.VQCodebook;
@@ -36,14 +36,14 @@ public class DebugFunction extends CustomFunctionBase {
             symbols[i] = i;
         }
 
-        final Huffman huffman = new Huffman(symbols, codebook.getVectorFrequencies());
+        final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, codebook.getVectorFrequencies());
         huffman.buildHuffmanTree();
 
         final int bitsPerSymbol = (int) Utils.log2(codebook.getCodebookSize());
         try (final OutBitStream bitStream = new OutBitStream(new FileOutputStream("D:\\tmp\\huffman_tree.data", false),
                                                              bitsPerSymbol,
                                                              64)) {
-            huffman.saveHuffmanTree(bitStream);
+            huffman.getRoot().writeToBinaryStream(bitStream);
         } catch (final IOException e) {
             e.printStackTrace();
         }
@@ -51,7 +51,7 @@ public class DebugFunction extends CustomFunctionBase {
 
         HuffmanNode readRoot = null;
         try (final InBitStream inBitStream = new InBitStream(new FileInputStream("D:\\tmp\\huffman_tree.data"), bitsPerSymbol, 256)) {
-            readRoot = Huffman.readHuffmanTree(inBitStream);
+            readRoot = HuffmanNode.readFromStream(inBitStream);
         } catch (final IOException ex) {
             ex.printStackTrace();
         }
diff --git a/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java b/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
index 22b328d64310d8764bcc1b61f1cfa15909aecc02..82d9453091fcfd1024a1f3413ee5e6fd7811662f 100644
--- a/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
+++ b/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
@@ -3,7 +3,7 @@ package cz.it4i.qcmp.compression;
 import cz.it4i.qcmp.compression.exception.ImageCompressionException;
 import cz.it4i.qcmp.compression.listeners.IProgressListener;
 import cz.it4i.qcmp.compression.listeners.IStatusListener;
-import cz.it4i.qcmp.huffman.Huffman;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
 import cz.it4i.qcmp.io.InputData;
 import cz.it4i.qcmp.io.OutBitStream;
 
@@ -100,8 +100,8 @@ public abstract class CompressorDecompressorBase {
         return symbols;
     }
 
-    protected Huffman createHuffmanCoder(final int[] symbols, final long[] frequencies) {
-        final Huffman huffman = new Huffman(symbols, frequencies);
+    protected HuffmanTreeBuilder createHuffmanCoder(final int[] symbols, final long[] frequencies) {
+        final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, frequencies);
         huffman.buildHuffmanTree();
         return huffman;
     }
@@ -157,7 +157,7 @@ public abstract class CompressorDecompressorBase {
      * @throws ImageCompressionException when fails to write to compress stream.
      */
     protected long writeHuffmanEncodedIndices(final DataOutputStream compressStream,
-                                              final Huffman huffman,
+                                              final HuffmanTreeBuilder huffman,
                                               final int[] indices) throws ImageCompressionException {
         try (final OutBitStream outBitStream = new OutBitStream(compressStream, options.getBitsPerCodebookIndex(), 2048)) {
             for (final int index : indices) {
diff --git a/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java b/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
index ec32d2c0127f9a9564b42ce2c9456c0aecd7ed2a..1e7c1ec7b2ac5a96f07c3280a28f109c8ec0f34e 100644
--- a/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
@@ -5,7 +5,7 @@ import cz.it4i.qcmp.cache.ICacheFile;
 import cz.it4i.qcmp.cache.QuantizationCacheManager;
 import cz.it4i.qcmp.cache.SQCacheFile;
 import cz.it4i.qcmp.compression.exception.ImageCompressionException;
-import cz.it4i.qcmp.huffman.Huffman;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
 import cz.it4i.qcmp.io.InputData;
 import cz.it4i.qcmp.io.loader.IPlaneLoader;
 import cz.it4i.qcmp.io.loader.PlaneLoaderFactory;
@@ -20,7 +20,7 @@ import java.io.IOException;
 public class SQImageCompressor extends CompressorDecompressorBase implements IImageCompressor {
 
     private ScalarQuantizer cachedQuantizer;
-    private Huffman cachedHuffman;
+    private HuffmanTreeBuilder cachedHuffman;
 
     public SQImageCompressor(final CompressionOptions options) {
         super(options);
@@ -116,7 +116,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
         }
 
         ScalarQuantizer quantizer = null;
-        Huffman huffman = null;
+        HuffmanTreeBuilder huffman = null;
         final int[] huffmanSymbols = createHuffmanSymbols(getCodebookSize());
         if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
             reportStatusToListeners("Loading codebook from cache file.");
@@ -174,7 +174,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
                 quantizer = trainScalarQuantizerFromData(planeData);
                 writeCodebookToOutputStream(quantizer, compressStream);
 
-                huffman = new Huffman(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
+                huffman = new HuffmanTreeBuilder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
                 huffman.buildHuffmanTree();
             }
 
diff --git a/src/main/java/cz/it4i/qcmp/compression/SQImageDecompressor.java b/src/main/java/cz/it4i/qcmp/compression/SQImageDecompressor.java
index 2cdfda862681de250c7cc022ef34def6c925a443..e72bfbb2baa95887536e68918ca3633bb681169c 100644
--- a/src/main/java/cz/it4i/qcmp/compression/SQImageDecompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/SQImageDecompressor.java
@@ -4,8 +4,8 @@ import cz.it4i.qcmp.cache.ICacheFile;
 import cz.it4i.qcmp.cache.SQCacheFile;
 import cz.it4i.qcmp.compression.exception.ImageDecompressionException;
 import cz.it4i.qcmp.fileformat.QCMPFileHeader;
-import cz.it4i.qcmp.huffman.Huffman;
 import cz.it4i.qcmp.huffman.HuffmanNode;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
 import cz.it4i.qcmp.io.InBitStream;
 import cz.it4i.qcmp.quantization.scalar.SQCodebook;
 import cz.it4i.qcmp.utilities.Stopwatch;
@@ -17,7 +17,7 @@ import java.io.IOException;
 
 public class SQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor {
     private SQCodebook cachedCodebook = null;
-    private Huffman cachedHuffman = null;
+    private HuffmanTreeBuilder cachedHuffman = null;
 
     public SQImageDecompressor(final CompressionOptions options) {
         super(options);
@@ -52,7 +52,7 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
         final int planePixelCount = header.getImageSizeX() * header.getImageSizeY();
 
         SQCodebook codebook = null;
-        Huffman huffman = null;
+        HuffmanTreeBuilder huffman = null;
         if (!header.isCodebookPerPlane()) {
             // There is only one codebook.
             reportStatusToListeners("Loading single codebook and huffman coder.");
@@ -130,7 +130,7 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
         final int planePixelCount = header.getImageSizeX() * header.getImageSizeY();
 
         SQCodebook codebook = null;
-        Huffman huffman = null;
+        HuffmanTreeBuilder huffman = null;
         if (!header.isCodebookPerPlane()) {
             // There is only one codebook.
             codebook = readScalarQuantizationValues(compressedStream, codebookSize);
diff --git a/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java b/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
index c64163aa97dc4d7e230aaa267ada320ecec5f035..90d3cfd7d2f1ebe8f3822ee47034e34e175bbac1 100644
--- a/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
@@ -6,7 +6,7 @@ import cz.it4i.qcmp.cache.VQCacheFile;
 import cz.it4i.qcmp.compression.exception.ImageCompressionException;
 import cz.it4i.qcmp.data.Range;
 import cz.it4i.qcmp.fileformat.QuantizationType;
-import cz.it4i.qcmp.huffman.Huffman;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
 import cz.it4i.qcmp.io.InputData;
 import cz.it4i.qcmp.io.loader.IPlaneLoader;
 import cz.it4i.qcmp.io.loader.PlaneLoaderFactory;
@@ -24,7 +24,7 @@ import java.io.IOException;
 public class VQImageCompressor extends CompressorDecompressorBase implements IImageCompressor {
 
     private VectorQuantizer cachedQuantizer = null;
-    private Huffman cachedHuffman = null;
+    private HuffmanTreeBuilder cachedHuffman = null;
 
     private boolean useKdTree = false;
 
@@ -158,7 +158,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
         }
 
         VectorQuantizer quantizer = cachedQuantizer;
-        Huffman huffman = cachedHuffman;
+        HuffmanTreeBuilder huffman = cachedHuffman;
         assert (!streamMode || ((quantizer != null) && (huffman != null)));
 
         if (!streamMode) {
@@ -283,7 +283,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
         final long[] voxelLayersSizes = new long[voxelLayerCount];
 
         final VectorQuantizer quantizer = (cachedQuantizer != null) ? cachedQuantizer : loadQuantizerFromCache();
-        final Huffman huffman = (cachedHuffman != null) ? cachedHuffman : createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies());
+        final HuffmanTreeBuilder huffman = (cachedHuffman != null) ? cachedHuffman : createHuffmanCoder(huffmanSymbols,
+                                                                                                        quantizer.getFrequencies());
         if (!streamMode)
             writeQuantizerToCompressStream(quantizer, compressStream);
 
diff --git a/src/main/java/cz/it4i/qcmp/compression/VQImageDecompressor.java b/src/main/java/cz/it4i/qcmp/compression/VQImageDecompressor.java
index 6be7248fdd550eee8f00f3626195c6149ec389e1..1da6828e3e2883ba57f761b676ea365929a005f4 100644
--- a/src/main/java/cz/it4i/qcmp/compression/VQImageDecompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/VQImageDecompressor.java
@@ -6,8 +6,8 @@ import cz.it4i.qcmp.compression.exception.ImageDecompressionException;
 import cz.it4i.qcmp.data.*;
 import cz.it4i.qcmp.fileformat.QCMPFileHeader;
 import cz.it4i.qcmp.fileformat.QuantizationType;
-import cz.it4i.qcmp.huffman.Huffman;
 import cz.it4i.qcmp.huffman.HuffmanNode;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
 import cz.it4i.qcmp.io.InBitStream;
 import cz.it4i.qcmp.quantization.vector.VQCodebook;
 import cz.it4i.qcmp.utilities.Stopwatch;
@@ -20,7 +20,7 @@ import java.io.IOException;
 public class VQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor {
 
     private VQCodebook cachedCodebook = null;
-    private Huffman cachedHuffman = null;
+    private HuffmanTreeBuilder cachedHuffman = null;
 
     private interface DecompressCallback {
         void process(final Block imageBlock, final int planeIndex) throws ImageDecompressionException;
@@ -90,7 +90,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
         }
         return reconstructedChunk;
     }
-    
+
     @Override
     public void decompress(final DataInputStream compressedStream,
                            final DataOutputStream decompressStream,
@@ -122,7 +122,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
 
 
         VQCodebook codebook = null;
-        Huffman huffman = null;
+        HuffmanTreeBuilder huffman = null;
         if (!header.isCodebookPerPlane()) {
             // There is only one codebook.
             codebook = readCodebook(compressedStream, codebookSize, vectorSize);
@@ -245,7 +245,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
 
 
         final VQCodebook codebook = readCodebook(compressedStream, codebookSize, vectorSize);
-        final Huffman huffman = createHuffmanCoder(huffmanSymbols, codebook.getVectorFrequencies());
+        final HuffmanTreeBuilder huffman = createHuffmanCoder(huffmanSymbols, codebook.getVectorFrequencies());
 
         final int voxelLayerCount = VQImageCompressor.calculateVoxelLayerCount(header.getImageSizeZ(), header.getVectorSizeZ());
         final Stopwatch stopwatch = new Stopwatch();
@@ -379,7 +379,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
         });
     }
 
-    private int decodeHuffmanSymbol(final Huffman huffman, final InBitStream inBitStream) throws IOException {
+    private int decodeHuffmanSymbol(final HuffmanTreeBuilder huffman, final InBitStream inBitStream) throws IOException {
         HuffmanNode currentHuffmanNode = huffman.getRoot();
         while (!currentHuffmanNode.isLeaf()) {
             currentHuffmanNode = currentHuffmanNode.traverse(inBitStream.readBit());
diff --git a/src/main/java/cz/it4i/qcmp/huffman/HuffmanNode.java b/src/main/java/cz/it4i/qcmp/huffman/HuffmanNode.java
index f81e5d3a7c944eb06e34f96f92559c91b14fdede..4d453675f2dc69c591954f38f5ed8acd79c395e6 100644
--- a/src/main/java/cz/it4i/qcmp/huffman/HuffmanNode.java
+++ b/src/main/java/cz/it4i/qcmp/huffman/HuffmanNode.java
@@ -1,36 +1,38 @@
 package cz.it4i.qcmp.huffman;
 
+import cz.it4i.qcmp.io.InBitStream;
+import cz.it4i.qcmp.io.OutBitStream;
 import org.jetbrains.annotations.NotNull;
 
+import java.io.IOException;
+
 public class HuffmanNode implements Comparable<HuffmanNode> {
     private int symbol = -1;
-    private long symbolFrequency = -1;
 
     private int bit = -1;
     private boolean leaf = false;
     private double probability = 0.0;
 
-    final HuffmanNode subNodeA;
-    final HuffmanNode subNodeB;
+    final HuffmanNode rightChild;
+    final HuffmanNode leftChild;
 
-    public HuffmanNode(final int symbol, final double probability, final long frequency) {
+    public HuffmanNode(final int symbol, final double probability) {
         this.symbol = symbol;
         this.probability = probability;
-        this.symbolFrequency = frequency;
-        subNodeA = null;
-        subNodeB = null;
+        rightChild = null;
+        leftChild = null;
         this.leaf = true;
     }
 
-    private HuffmanNode(final HuffmanNode parentA, final HuffmanNode parentB) {
-        subNodeA = parentA;
-        subNodeB = parentB;
+    private HuffmanNode(final HuffmanNode rightChild, final HuffmanNode leftChild) {
+        this.rightChild = rightChild;
+        this.leftChild = leftChild;
     }
 
-    public static HuffmanNode constructWithSymbol(final HuffmanNode parentA, final HuffmanNode parentB, final int symbol) {
-        final HuffmanNode node = new HuffmanNode(parentA, parentB);
+    public static HuffmanNode constructWithSymbol(final HuffmanNode rightChild, final HuffmanNode leftChild, final int symbol) {
+        final HuffmanNode node = new HuffmanNode(rightChild, leftChild);
         node.symbol = symbol;
-        node.leaf = (parentA == null && parentB == null);
+        node.leaf = (rightChild == null && leftChild == null);
         return node;
     }
 
@@ -41,10 +43,10 @@ public class HuffmanNode implements Comparable<HuffmanNode> {
     }
 
     public HuffmanNode traverse(final boolean queryBit) {
-        if (subNodeA != null && subNodeA.bit == (queryBit ? 1 : 0))
-            return subNodeA;
-        if (subNodeB != null && subNodeB.bit == (queryBit ? 1 : 0))
-            return subNodeB;
+        if (rightChild != null && rightChild.bit == (queryBit ? 1 : 0))
+            return rightChild;
+        if (leftChild != null && leftChild.bit == (queryBit ? 1 : 0))
+            return leftChild;
 
         assert (false) : "Corrupted huffman tree";
         return null;
@@ -63,10 +65,6 @@ public class HuffmanNode implements Comparable<HuffmanNode> {
         return symbol;
     }
 
-    public long getSymbolFrequency() {
-        return symbolFrequency;
-    }
-
     public int getBit() {
         return bit;
     }
@@ -79,39 +77,104 @@ public class HuffmanNode implements Comparable<HuffmanNode> {
         return probability;
     }
 
-    public HuffmanNode getSubNodeA() {
-        return subNodeA;
+    public HuffmanNode getRightChild() {
+        return rightChild;
     }
 
-    public HuffmanNode getSubNodeB() {
-        return subNodeB;
+    public HuffmanNode getLeftChild() {
+        return leftChild;
     }
 
-    private static boolean treeNodeEquality(final HuffmanNode A, final HuffmanNode B) {
-        if (A.leaf) {
-            if (!B.leaf) {
+    /**
+     * Check if two huffman nodes are value equal and if their subtrees are also equal.
+     *
+     * @param nodeA First huffman node.
+     * @param nodeB Second huffman code.
+     * @return True if nodes and their subtrees are equal.
+     */
+    private static boolean treeNodeEquality(final HuffmanNode nodeA, final HuffmanNode nodeB) {
+        if (nodeA.leaf) {
+            if (!nodeB.leaf) {
                 return false;
             }
-            return A.symbol == B.symbol;
+            return nodeA.symbol == nodeB.symbol;
         } else {
-            if (B.leaf) {
+            if (nodeB.leaf) {
                 return false;
             }
-            if (A.bit != B.bit)
+            if (nodeA.bit != nodeB.bit)
                 return false;
 
-            if ((A.subNodeA != null && B.subNodeA == null) || (A.subNodeA == null && B.subNodeA != null))
+            if ((nodeA.rightChild != null && nodeB.rightChild == null) || (nodeA.rightChild == null && nodeB.rightChild != null))
                 return false;
-            if ((A.subNodeB != null && B.subNodeB == null) || (A.subNodeB == null && B.subNodeB != null))
+            if ((nodeA.leftChild != null && nodeB.leftChild == null) || (nodeA.leftChild == null && nodeB.leftChild != null))
                 return false;
 
-            final boolean subTreeAResult = treeNodeEquality(A.subNodeA, B.subNodeA);
-            final boolean subTreeBResult = treeNodeEquality(A.subNodeB, B.subNodeB);
+
+            assert (nodeA.rightChild != null) : "Current node is not leaf and right child must be set.";
+            assert (nodeA.leftChild != null) : "Current node is not leaf and left child must be set.";
+
+            final boolean subTreeAResult = treeNodeEquality(nodeA.rightChild, nodeB.rightChild);
+            final boolean subTreeBResult = treeNodeEquality(nodeA.leftChild, nodeB.leftChild);
             return (subTreeAResult && subTreeBResult);
         }
     }
 
-    public boolean treeEqual(final HuffmanNode opposite) {
-        return treeNodeEquality(this, opposite);
+    /**
+     * Check if tree starting from this node is equal to one starting from otherRoot.
+     *
+     * @param otherRoot Other tree root node.
+     * @return True if both trees are value equal.
+     */
+    public boolean treeEqual(final HuffmanNode otherRoot) {
+        return treeNodeEquality(this, otherRoot);
+    }
+
+    /**
+     * Save current node and its children to binary stream.
+     *
+     * @param node      Node to write to stream.
+     * @param bitStream Binary output stream.
+     * @throws IOException when fails to write to stream.
+     */
+    private void writeToBinaryStreamImpl(final HuffmanNode node, final OutBitStream bitStream) throws IOException {
+        if (node.isLeaf()) {
+            bitStream.writeBit(1);
+            bitStream.write(node.getSymbol());
+        } else {
+            bitStream.writeBit(0);
+            writeToBinaryStreamImpl(node.getRightChild(), bitStream);
+            writeToBinaryStreamImpl(node.getLeftChild(), bitStream);
+        }
+    }
+
+    /**
+     * Save huffman tree from this node to the binary stream.
+     *
+     * @param bitStream Binary output stream.
+     * @throws IOException when fails to write to stream.
+     */
+    public void writeToBinaryStream(final OutBitStream bitStream) throws IOException {
+        writeToBinaryStreamImpl(this, bitStream);
+    }
+
+    /**
+     * Read huffman tree from the binary stream.
+     *
+     * @param bitStream Binary input stream.
+     * @return Root of the huffman tree.
+     * @throws IOException when fails to read from stream.
+     */
+    public static HuffmanNode readFromStream(final InBitStream bitStream) throws IOException {
+        if (bitStream.readBit()) // Leaf
+        {
+            return HuffmanNode.constructWithSymbol(null, null, bitStream.readValue());
+        } else {
+            final HuffmanNode rightChild = readFromStream(bitStream);
+            rightChild.setBit(1);
+            final HuffmanNode leftChild = readFromStream(bitStream);
+            leftChild.setBit(0);
+            return HuffmanNode.constructWithSymbol(rightChild, leftChild, -1);
+        }
     }
 }
\ No newline at end of file
diff --git a/src/main/java/cz/it4i/qcmp/huffman/Huffman.java b/src/main/java/cz/it4i/qcmp/huffman/HuffmanTreeBuilder.java
similarity index 67%
rename from src/main/java/cz/it4i/qcmp/huffman/Huffman.java
rename to src/main/java/cz/it4i/qcmp/huffman/HuffmanTreeBuilder.java
index 4601e9725e484484ed5c460217f5938f1b309a7d..5daf0ae9782064ac07789aff49751d841f318535 100644
--- a/src/main/java/cz/it4i/qcmp/huffman/Huffman.java
+++ b/src/main/java/cz/it4i/qcmp/huffman/HuffmanTreeBuilder.java
@@ -1,19 +1,15 @@
 package cz.it4i.qcmp.huffman;
 
-import cz.it4i.qcmp.io.InBitStream;
-import cz.it4i.qcmp.io.OutBitStream;
-
-import java.io.IOException;
 import java.util.*;
 
-public class Huffman {
+public class HuffmanTreeBuilder {
     private HuffmanNode root = null;
     private HashMap<Integer, boolean[]> symbolCodes;
     private HashMap<Integer, Double> symbolProbabilityMap;
     private final int[] symbols;
     private final long[] symbolFrequencies;
 
-    public Huffman(final int[] symbols, final long[] symbolFrequencies) {
+    public HuffmanTreeBuilder(final int[] symbols, final long[] symbolFrequencies) {
         assert (symbols.length == symbolFrequencies.length) : "Array lengths mismatch";
         this.symbols = symbols;
         this.symbolFrequencies = symbolFrequencies;
@@ -57,14 +53,14 @@ public class Huffman {
             currentCode.add(bit == 1);
         }
 
-        if (currentNode.subNodeA != null) {
+        if (currentNode.rightChild != null) {
             final ArrayList<Boolean> codeCopy = new ArrayList<Boolean>(currentCode);
-            traverseSymbolCodes(currentNode.subNodeA, codeCopy);
+            traverseSymbolCodes(currentNode.rightChild, codeCopy);
             inLeaf = false;
         }
-        if (currentNode.subNodeB != null) {
+        if (currentNode.leftChild != null) {
             final ArrayList<Boolean> codeCopy = new ArrayList<Boolean>(currentCode);
-            traverseSymbolCodes(currentNode.subNodeB, codeCopy);
+            traverseSymbolCodes(currentNode.leftChild, codeCopy);
             inLeaf = false;
         }
 
@@ -93,7 +89,7 @@ public class Huffman {
         for (int sIndex = 0; sIndex < symbols.length; sIndex++) {
             final double symbolProbability = (double) symbolFrequencies[sIndex] / totalFrequency;
             symbolProbabilityMap.put(symbols[sIndex], symbolProbability);
-            queue.add(new HuffmanNode(symbols[sIndex], symbolProbability, symbolFrequencies[sIndex]));
+            queue.add(new HuffmanNode(symbols[sIndex], symbolProbability));
         }
 
         return queue;
@@ -115,12 +111,7 @@ public class Huffman {
     private HashMap<Integer, Double> createSortedHashMap(final HashMap<Integer, Double> map) {
         final List<Map.Entry<Integer, Double>> list = new LinkedList<Map.Entry<Integer, Double>>(map.entrySet());
         //Custom Comparator
-        list.sort(new Comparator<Map.Entry<Integer, Double>>() {
-            @Override
-            public int compare(final Map.Entry<Integer, Double> t0, final Map.Entry<Integer, Double> t1) {
-                return -(t0.getValue().compareTo(t1.getValue()));
-            }
-        });
+        list.sort((t0, t1) -> (-(t0.getValue().compareTo(t1.getValue()))));
         //copying the sorted list in HashMap to preserve the iteration order
         final HashMap<Integer, Double> sortedHashMap = new LinkedHashMap<Integer, Double>();
         for (final Map.Entry<Integer, Double> entry : list) {
@@ -128,38 +119,4 @@ public class Huffman {
         }
         return sortedHashMap;
     }
-
-    private void encodeHuffmanNode(final HuffmanNode node, final OutBitStream bitStream) throws IOException {
-        if (node.isLeaf()) {
-            bitStream.writeBit(1);
-            bitStream.write(node.getSymbol());
-        } else {
-            bitStream.writeBit(0);
-            encodeHuffmanNode(node.getSubNodeA(), bitStream);
-            encodeHuffmanNode(node.getSubNodeB(), bitStream);
-        }
-    }
-
-    private static HuffmanNode decodeHuffmanNode(final InBitStream bitStream) throws IOException {
-        if (bitStream.readBit()) // Leaf
-        {
-            return HuffmanNode.constructWithSymbol(null, null, bitStream.readValue());
-        } else {
-            final HuffmanNode nodeA = decodeHuffmanNode(bitStream);
-            nodeA.setBit(1);
-            final HuffmanNode nodeB = decodeHuffmanNode(bitStream);
-            nodeB.setBit(0);
-            return HuffmanNode.constructWithSymbol(nodeA, nodeB, -1);
-        }
-    }
-
-
-    public void saveHuffmanTree(final OutBitStream bitStream) throws IOException {
-        assert root != null : "The tree is not build.";
-        encodeHuffmanNode(root, bitStream);
-    }
-
-    public static HuffmanNode readHuffmanTree(final InBitStream bitStream) throws IOException {
-        return decodeHuffmanNode(bitStream);
-    }
 }