import structure.*; import com.mw.io.*; public class Huffmantest { //+main public static void main(String args[]) { ReadStream r = new ReadStream(); List freq = new SinglyLinkedList(); // new variable for storing the message as it is read String message = ""; // read data from input while (!r.eof()) { char c = r.readChar(); //-main if (c == '\n') continue; //+main // build the message message = message + c; // look up character in frequency list leaf query = new leaf(c); leaf item = (leaf)freq.remove(query); if (item == null) { // not found, add new leaf freq.add(query); } else { // found, increment leaf item.frequency++; freq.add(item); } } // insert each character into a huffman tree Iterator li = freq.elements(); //+mergingPhase OrderedList trees = new OrderedList(); //-mergingPhase for (li.reset(); li.hasMoreElements(); li.nextElement()) { trees.add(new huffmanTree((leaf)li.value())); } //+mergingPhase // merge trees in pairs until one remains Iterator ti = trees.elements(); while (trees.size() > 1) { // construct a new iterator ti = trees.elements(); // grab two smallest values huffmanTree smallest = (huffmanTree)ti.nextElement(); huffmanTree small = (huffmanTree)ti.nextElement(); // remove them trees.remove(smallest); trees.remove(small); // add bigger tree containing both trees.add(new huffmanTree(smallest,small)); } // print only leaf in tree list ti = trees.elements(); huffmanTree encoding = (huffmanTree)ti.value(); //-mergingPhase encoding.print(); // display the Huffman encodings encoding.count(); // display the length of the encoded string encoding.encode(message); // encode and display the message } //-main } //+leaf class leaf { int frequency; // frequency of char char ch; // the character public leaf(char c) // post: construct character entry with frequency 1 //-leaf { ch = c; frequency = 1; } //+leaf public boolean equals(Object other) // post: return true if leaves represent same character //-leaf { leaf that = (leaf)other; return this.ch == that.ch; } //+leaf } //-leaf //+huffmanTree class huffmanTree implements Comparable { BinaryTreeNode root; // root of tree int totalWeight; // weight of tree public huffmanTree(leaf e) // post: construct a leaf with associated character //-huffmanTree { root = new BinaryTreeNode(e); totalWeight = e.frequency; } //+huffmanTree public huffmanTree(huffmanTree left, huffmanTree right) // pre: left and right non-null // post: merge two trees together and total weights //-huffmanTree { this.totalWeight = left.totalWeight + right.totalWeight; root = new BinaryTreeNode(null,left.root,right.root); } //+huffmanTree public boolean lessThan(Comparable other) // pre: other is not null // post: return true if this tree weighs less than other //-huffmanTree { huffmanTree that = (huffmanTree)other; return this.totalWeight < that.totalWeight; } //+huffmanTree public boolean equals(Object that) // post: return true if this and that are same tree instance //-huffmanTree { return this == that; } //+huffmanTree public void print() // post: print out strings associated with characters in tree //-huffmanTree { print(this.root,""); } //+huffmanTree protected void print(BinaryTreeNode r, String representation) // post: print out strings associated with chars in tree r, // prefixed by representation //-huffmanTree { if (r.left() != null) { // interior node print(r.left(),representation+"0"); // append a 0 print(r.right(),representation+"1"); // append a 1 } else { // leaf; print encoding leaf e = (leaf)r.value(); System.out.println("Encoding of "+e.ch+" is "+ representation+" (frequency was "+e.frequency+")"); } } //+huffmanTree public void count() // post: compute and display the length of the encoded string //-huffmanTree { Integer sum = new Integer(0); count(this.root, "", sum); System.out.println("Total length of encoded message = " + sum.intValue()); } //+huffmanTree protected void count(BinaryTreeNode r, String representation, Integer sum) // post: traverse the tree to all leaves, adding the frequency * the path // length to the sum each time a leaf is reached. //-huffmanTree { if (r.left() != null) { // interior node count(r.left(),representation+"0", sum); // append a 0 count(r.right(),representation+"1", sum); // append a 1 } else { // leaf; add to accumulated length (sum) leaf e = (leaf)r.value(); int charLength = e.frequency*(representation.length()); sum = new Integer(sum.intValue() + charLength); } } //+huffmanTree public void encode(String message) // post: encode the message and display it //-huffmanTree { // A vector of encodings for the characters in the message // Each encoding is a string whose first character is a letter // and whose remaining characters define the binary code for that // letter. Vector encodings = new Vector(); encode(this.root, "", encodings); // develop the vector of characters and their encodings String pair = ""; // now go back through the message and display the encoding for each // character in its original place System.out.println("The encoded message = "); for (int i=0; i