Java Algorithms Huffman code

Description

Java Algorithms Huffman code

public class Main {
  public static void main(String[] args) {
    // Count frequency
    int[] counts = getCharacterFrequency("this is a test test test");

    System.out.printf("%-15s%-15s%-15s%-15s\n", "ASCII Code", "Character", "Frequency", "Code");

    Tree tree = getHuffmanTree(counts); // Create a Huffman tree
    String[] codes = getCode(tree.root); // Get codes

    for (int i = 0; i < codes.length; i++) {
      if (counts[i] != 0) {// (char)i is not in text if counts[i] is 0
        System.out.printf("%-15d%-15s%-15d%-15s\n", i, (char) i + "", counts[i], codes[i]);
      }/*from  ww w  . ja va2  s . co m*/
    }
  }
  /**
   * Get Huffman codes for the characters This method is called once after a
   * Huffman tree is built
   */
  public static String[] getCode(Node root) {
    if (root == null)
      return null;
    String[] codes = new String[2 * 128];
    assignCode(root, codes);
    return codes;
  }
  /* Recursively get codes to the leaf node */
  private static void assignCode(Node root, String[] codes) {
    if (root.left != null) {
      root.left.code = root.code + "0";
      assignCode(root.left, codes);

      root.right.code = root.code + "1";
      assignCode(root.right, codes);
    } else {
      codes[(int) root.element] = root.code;
    }
  }

  /** Get a Huffman tree from the codes */
  public static Tree getHuffmanTree(int[] counts) {
    // Create a heap to hold trees
    Heap<Tree> heap = new Heap<>(); // Defined in Listing 24.10
    for (int i = 0; i < counts.length; i++) {
      if (counts[i] > 0)
        heap.add(new Tree(counts[i], (char) i)); // A leaf node tree
    }

    while (heap.getSize() > 1) {
      Tree t1 = heap.remove(); // Remove the smallest weight tree
      Tree t2 = heap.remove(); // Remove the next smallest weight
      heap.add(new Tree(t1, t2)); // Combine two trees
    }
    return heap.remove(); // The final tree
  }
  public static int[] getCharacterFrequency(String text) {
    int[] counts = new int[256]; // 256 ASCII characters
    for (int i = 0; i < text.length(); i++)
      counts[(int) text.charAt(i)]++; // Count the character in text

    return counts;
  }
}

/** Huffman coding tree */
class Tree implements Comparable<Tree> {
  Node root; // The root of the tree

  /** Create a tree with two subtrees */
  public Tree(Tree t1, Tree t2) {
    root = new Node();
    root.left = t1.root;
    root.right = t2.root;
    root.weight = t1.root.weight + t2.root.weight;
  }

  /** Create a tree containing a leaf node */
  public Tree(int weight, char element) {
    root = new Node(weight, element);
  }

  @Override /** Compare trees based on their weights */
  public int compareTo(Tree t) {
    if (root.weight < t.root.weight) // Purposely reverse the order
      return 1;
    else if (root.weight == t.root.weight)
      return 0;
    else
      return -1;
  }

}

class Node {
  char element; // Stores the character for a leaf node
  int weight; // weight of the subtree rooted at this node
  Node left; // Reference to the left subtree
  Node right; // Reference to the right subtree
  String code = ""; // The code of this node from the root

  public Node() {
  }
  public Node(int weight, char element) {
    this.weight = weight;
    this.element = element;
  }
}

class Heap<E extends Comparable> {
  private java.util.ArrayList<E> list = new java.util.ArrayList<E>();

  public Heap() {
  }

  public Heap(E[] objects) {
    for (int i = 0; i < objects.length; i++)
      add(objects[i]);
  }

  public void add(E newObject) {
    list.add(newObject); // Append to the heap
    int currentIndex = list.size() - 1; // The index of the last node

    while (currentIndex > 0) {
      int parentIndex = (currentIndex - 1) / 2;
      // Swap if the current object is greater than its parent
      if (list.get(currentIndex).compareTo(list.get(parentIndex)) > 0) {
        E temp = list.get(currentIndex);
        list.set(currentIndex, list.get(parentIndex));
        list.set(parentIndex, temp);
      } else
        break; // the tree is a heap now

      currentIndex = parentIndex;
    }
  }

  public E remove() {
    if (list.size() == 0)
      return null;

    E removedObject = list.get(0);
    list.set(0, list.get(list.size() - 1));
    list.remove(list.size() - 1);

    int currentIndex = 0;
    while (currentIndex < list.size()) {
      int leftChildIndex = 2 * currentIndex + 1;
      int rightChildIndex = 2 * currentIndex + 2;

      // Find the maximum between two children
      if (leftChildIndex >= list.size())
        break; // The tree is a heap
      int maxIndex = leftChildIndex;
      if (rightChildIndex < list.size()) {
        if (list.get(maxIndex).compareTo(list.get(rightChildIndex)) < 0) {
          maxIndex = rightChildIndex;
        }
      }

      // Swap if the current node is less than the maximum
      if (list.get(currentIndex).compareTo(list.get(maxIndex)) < 0) {
        E temp = list.get(maxIndex);
        list.set(maxIndex, list.get(currentIndex));
        list.set(currentIndex, temp);
        currentIndex = maxIndex;
      } else
        break; // The tree is a heap
    }

    return removedObject;
  }

  public int getSize() {
    return list.size();
  }
}



PreviousNext

Related