/**************************************************** * CS2510 Fall 2011 * Lecture #32 * Huffman Codes Finished ****************************************************/ import tester.*; import java.util.*; // Huffman Codes class class Huffman { HashMap code = new HashMap(); HashMap revcode = new HashMap(); // generate Code void genCode(ArrayList in){ HashMap counts = new HashMap(); for(String s : in) { if (counts.containsKey(s)) { counts.put(s,counts.get(s)+1); } else { counts.put(s,1); } } PriorityQueue pq = new PriorityQueue(); for(String s : counts.keySet()) { pq.add(new Leaf(s,counts.get(s))); } while(pq.size() > 1) { Tree one = pq.remove(); Tree two = pq.remove(); pq.add(new Node(one,two)); } treeToMap(pq.remove()); } // Adds the given tree to the hashMaps by traversing and // assigns 0's to lefts and 1's to rights void treeToMap(Tree t) { treeToMapHelp(t,""); } // Accumulates the representation of the path so far void treeToMapHelp(Tree t, String rep) { if(t.isLeaf()) { code.put(t.val(), Integer.parseInt(rep)); revcode.put(Integer.parseInt(rep), t.val()); } else { treeToMapHelp(t.left(),rep+"0"); treeToMapHelp(t.right(),rep+"1"); } } // encode the given string list into the encoding ArrayList encode(ArrayList in) { ArrayList output = new ArrayList(); for (String s : in) { output.add(code.get(s)); } return output; } // decode the given encoding list into the original string list ArrayList decode(ArrayList in) { ArrayList output = new ArrayList(); for (Integer i : in) { output.add(revcode.get(i)); } return output; } } // A tree for representing the Huffman code interface Tree extends Comparable{ // Is this a leaf boolean isLeaf(); // Get the left Tree left(); // Get the right Tree right(); // Get the val String val(); // Get the count int count(); } // The Leaf element of the tree class Leaf implements Tree{ String s; int c; Leaf(String s, int c) { this.s = s; this.c = c; } public boolean isLeaf() { return true; } public Tree left() { throw new RuntimeException("No left in sight"); } public Tree right() { throw new RuntimeException("No right in sight"); } // Get the val public String val() { return s; } // Get the count public int count() { return c; } // Smaller elements are "lesser" public int compareTo(Tree o) { if (c < o.count()) { return -1; } else if (c > o.count()) { return 1; } else { return 0; } } // Are these leaves equal? public boolean equals(Object o) { if (o.getClass() == Leaf.class) { Leaf tmp = (Leaf) o; return (s == tmp.s) && (c == tmp.c); } else { return false; } } } // The node element of the tree class Node implements Tree{ Tree left; Tree right; Node(Tree left, Tree right) { this.left = left; this.right = right; } public boolean isLeaf() { return false; } public Tree left() { return left; } public Tree right() { return right; } // Get the val public String val() { throw new RuntimeException("Nodes have no value."); } // Get the count public int count() { return left.count() + right.count(); } // Smaller elements are "lesser" public int compareTo(Tree o) { if (count() < o.count()) { return -1; } else if (count() > o.count()) { return 1; } else { return 0; } } // Are these nodes equal? // Does not allow for loops in a tree public boolean equals(Object o) { if (o.getClass() == Node.class) { Node tmp = (Node) o; return (left.equals(tmp.left) && right.equals(tmp.right)); } else { return false; } } } class Pair implements Comparable { String s; Integer i; Pair(String s, Integer i) { this.s = s; this.i = i; } // Smaller elements are "lesser" @Override public int compareTo(Pair o) { if (i < o.i) { return -1; } else if (i > o.i){ return 1; } else { return 0; } } public boolean equals(Object o) { if (o.getClass() == Pair.class) { Pair tmp = (Pair) o; return (s == tmp.s) && (i == tmp.i); } else { return false; } } } class Lecture_30 { public static void main(String args[]) { Huffman huff = new Huffman(); ArrayList a = new ArrayList(); for(String s : args) { for (String c : s.split("")) { a.add(c); } } huff.genCode(a); System.out.println(a); System.out.println(huff.encode(a)); System.out.println(huff.decode(huff.encode(a))); } } class LectureExamples { ArrayList input = new ArrayList(Arrays.asList("a","b","a","c","d","a","a","b")); Huffman huff = new Huffman(); // Clears testing state void reset() { huff = new Huffman(); } void testTreeToMap(Tester t) { reset(); Tree tree = new Node(new Leaf("a",4),new Node(new Leaf("b",3), new Leaf("c",2))); huff.treeToMap(tree); t.checkExpect(huff.code.get("a"),0); t.checkExpect(huff.code.get("b"),10); t.checkExpect(huff.code.get("c"),11); t.checkExpect(huff.revcode.get(0),"a"); t.checkExpect(huff.revcode.get(10),"b"); t.checkExpect(huff.revcode.get(11),"c"); } // Tests of genCode void testGenCode(Tester t) { reset(); huff.genCode(input); t.checkExpect(huff.code.containsKey("a"), true); t.checkExpect(huff.code.get("a"), 0); t.checkExpect(huff.code.get("d"), 110); t.checkExpect(huff.revcode.containsKey(0), true); t.checkExpect(huff.revcode.get(0), "a"); t.checkExpect(huff.revcode.get(111), "c"); } // Tests of encode void testEncode(Tester t) { reset(); huff.genCode(input); ArrayList in1 = new ArrayList(Arrays.asList("a","b","a")); ArrayList out1 = new ArrayList(Arrays.asList(0,10,0)); t.checkExpect(huff.encode(in1),out1); Iterator out1i = out1.iterator(); for(Integer i : huff.encode(in1)) { t.checkExpect(i,out1i.next()); } } // Tests of decode void testDecode(Tester t) { reset(); huff.genCode(input); ArrayList in1 = new ArrayList(Arrays.asList(0,10,0)); ArrayList out1 = new ArrayList(Arrays.asList("a","b","a")); t.checkExpect(huff.decode(in1),out1); Iterator out1i = out1.iterator(); for(String i : huff.decode(in1)) { t.checkExpect(i,out1i.next()); } } }