The file Assmt3Files contains all the classes that are provided
with this assignment. Use the classes from this provided zip file.
You are not allowed to make any change to any of these provided
classes. We proceed to briefly describe them, one by one:
• Class ArrayIterator.java: Unchanged from course website
• Class ArrayList.java: A method public T getElement(int i) to get the i-th element from the list was added
• Class ArrayOrderedList.java: Unchanged from course website
• Class ArrayUnorderedList.java: Unchanged from course website • Interface BinaryTreeADT.java: modified to mirror LinkedBinaryTree.java
• Class BinaryTreeNode.java: modified such that the attributes are private with their getter and setter methods implemented. A method public Boolean isLeaf() has been added. It returns true if a node is a leaf and false otherwise.
• Class CompressedFile.java • Class
ElementNotFoundException.java• Class EmptyCollectionException.java•
Class Huffman.java• Class HuffmanPair.java• Class
LinkedBinaryTree.java• Interface ListADT.java• Class
OrderedListADT.java• Class TextFile.java • Class
UnorderedListADT.java • Class TestEncodingData• Class
TestHuffmanTree• Class TestHuffmanEncoder
Assignment Tasks
Write a program according to the specifications found below,
that: • compresses a text file into a Huffman-encoded file,
generating the symbol frequency file for that particular text file
• decodes a Huffman-encoded file into a text file, using the symbol
frequency file for that particular file Functional Specifications
Your implementation will contain the following classes, according
to the specifications given in this document: • EncodingData.java •
HuffmanTree.java • HuffmanCoder.java
Class EncodingData.java:
This class is for you to write and represents a single pair of
the data used to encode a text message into its binary Huffman code
(a symbol and its corresponding binary Huffman code). It will be
used for encoding a text file. Your implementation of the
EncodingData class must include the following, with the method
headers as specified:
Attributes: private char symbol: a symbol that is to be encoded
private String encoding: the binary Huffman code of the symbol
(i.e. a string of 0’s and 1’s) Constructor: public
EncodingData(char symbol, String encoding) Public methods: •
getSymbol(), getEncoding(), setEncoding(): getter and setter
methods for both attributes • public boolean equals(Object obj):
method that determines if two EncodingData objects are equal based
on the symbol attribute (implement it in the same fashion as the
equals(Object obj) in the class HuffmanPair) • public String
toString(): method that gives a string representation of the symbol
and its Huffman code
Class HuffmanTree.java:
This class is for you to write and represents a Huffman tree,
and will extend the LinkedBinaryTree<T> class. It will also
implement the Comparable interface. Your implementation of the
class public class HuffmanTree extends
LinkedBinaryTree<HuffmanPair> implements
Comparable<HuffmanTree> must follow the specifications below,
with the method headers as specified.
Constructors to write: The HuffmanTree class will have 4
constructors and the first three will call the appropriate
constructor from the superclass (in this case, the LinkedBinaryTree
class): • public HuffmanTree(): creates an empty Huffman tree •
public HuffmanTree(HuffmanPair element): creates a Huffman tree
with one Huffman pair at the root • public HuffmanTree(HuffmanPair
element, HuffmanTree leftSubtree, HuffmanTree rightSubtree) creates
a Huffman tree rooted at a node containing element, where the roots
of the left subtree and right subtree are its left child and right
child, respectively.
The 4th constructor is: • public
HuffmanTree(ArrayOrderedList<HuffmanPair> pairsList)
The pairsList parameter is an ordered list of Huffman pairs in
ascending order by frequency (the file containing the symbols and
their frequencies for a text file is built for you by the Huffman
class (provided) when the file is encoded. The same frequency file
is used when the text file is decoded). This constructor will build
the Huffman tree from this ordered list of Huffman pairs.
In this constructor, the Huffman tree will be built using the
following algorithm. Wherever the algorithm refers to “trees”, it
means Huffman trees:
1. For each HuffmanPair in pairsList, make a HuffmanTree consisting
only of a root node containing the HuffmanPair, and add each tree
to a temporary ordered list buildList.
2. While there is more than one item in buildList
• Remove the 2 trees with the lowest frequencies in their root node
from buildList (Hint: they will be the first 2 trees in the list) •
Construct a new tree such that the first tree that was removed from
the list is the left subtree, the second tree removed is the right
subtree, and the root node of the new tree contains a new Huffman
pair whose frequency is the sum of the frequencies in the Huffman
pairs of the two children. (Hint: use the third constructor for a
Huffman tree) • Add the new tree into the ordered list buildList
such that the frequencies are maintained in ascending order (Hint:
the add method will insert it in the proper place)
3. The tree left in buildList is the final Huffman tree
Pay attention to the case when there is only one HuffmanPair.
This happens when a text file contains one or more instances of the
same character. In this case, the resulting Huffman tree has only
one root node and does not provide any decoding path. Find a simple
way to deal with this problem. Methods to write:
1. public int compareTo(HuffmanTree otherTree): This is the
compareTo method specified in the Comparable interface, so that you
will need to have the HuffmanTree class implement the Comparable
interface. It will compare the frequencies in the root node of the
trees, so that the add method of ArrayOrderedList can put that node
in its correct place in the ordered list buildList in the algorithm
to build a Huffman tree. 2. public String toString() : This method
will return a string representation of a Huffman tree by doing a
preorder traversal of the tree. It overrides the toString method of
the LinkedBinaryTree class
Class HuffmanCoder.java:
This class uses a Huffman tree for encoding a character and decoding a code string. Your implementation of the HuffmanCoder class must follow the specifications below, with the method headers as specified. Attributes: • private HuffmanTree huffTree: the Huffman tree • private ArrayUnorderedList<EncodingData> encodingList: an unordered list of encoding data that will be used for encoding a text file into a Huffman-coded compressed file Constructor to write: • public HuffmanCoder(ArrayOrderedList<HuffmanPair> pairsList): this constructor will create the huffTree, using the 4th Huffman tree constructor. It will also call the private helper method buildEncodingList(BinaryTreeNode<HuffmanPair> node, String encoding) which will build the list of symbols and their encodings from the Huffman tree huffTree. See below for further instructions. Methods to write: • public char decode(String code): This method will take the specified string of binary digits that is a Huffman encoding, and will return the original coded character. It will use the following decoding technique: as you get each character from the parameter string, traverse the tree beginning at the root, taking the left-hand path if the character is 0 and the right-hand path if the character is 1. When you encounter a leaf, you have found the symbol that was encoded. If the string of binary digits code does not lead to a leaf node, then the method must return (char) 0. • public String encode(char c)throws ElementNotFoundException: This method will take the specified character and return the string representation of the binary Huffman encoding of that character. • public String toString(): This method will return a string representation of the encoding list. • private void buildEncodingList (BinaryTreeNode<HuffmanPair> node, String encoding): This method will build the unordered list encodingList (an attribute of the HuffmanCoder class) from the Huffman tree huffTree. The list encodingList will be a list of EncodingData objects. This method will add new EncodingData objects to encodingList recursively, following this algorithm: if the parameter node is a leaf node add a new EncodingData object whose symbol is the character in the Huffman pair of that node and whose encoding is the second parameter encoding else call buildEncodingList with the left child of node and encoding with character ‘0’ appended call buildEncodingList with the right child of node and encoding with character ‘1’ appended .
EncodingData.java
public class EncodingData {
private char symbol;
private String encoding;
/**
* consutructor for making the encoding
data
* @param symbol
* @param encoding
*/
public EncodingData(char symbol, String
encoding) {
this.symbol =
symbol;
this.encoding =
encoding;
}
/**
* gets the symbol
* @return
*/
public char getSymbol() {
return this.symbol;
}
/**
* get the encoding
* @return
*/
public String getEncoding() {
return
this.encoding;
}
/**
* set the encoding
* @param encoding
*/
public void setEncoding(String encoding)
{
this.encoding =
encoding;
}
/**
* is the object equal
* @param obj
* @return
*/
public boolean equals(Object obj) {
if
(obj.equals(this.symbol)) {
return true;
} else {
return false;
}
}
/**
* returns string representation of the
encoding data
* @return
*/
public String toString() {
return this.symbol +
encoding;
}
}
HuffmanTree.java
import java.util.Iterator;
public class HuffmanTree extends LinkedBinaryTree<HuffmanPair> implements Comparable<HuffmanTree> {
/**
* constructor to make empty huffman
tree
*/
public HuffmanTree() {
super();
}
/**
* constructor to make huffman tree that
has 1 node, and element being root
* @param element
*/
public HuffmanTree(HuffmanPair element) {
super(element);
}
/**
* huffman tree that has root as element
and left and right child as leftsubtree and rightsubtree,
* @param element
* @param leftSubtree
* @param rightSubtree
*/
public HuffmanTree(HuffmanPair element,
HuffmanTree leftSubtree, HuffmanTree rightSubtree) {
super(element);
this.getRoot().setLeft(leftSubtree.getRoot());
this.getRoot().setRight(rightSubtree.getRoot());
}
/**
* creates a huffman tree in ascending
order, with a list of huffman pairs sent as arguments.
* @param pairsList
*/
public
HuffmanTree(ArrayOrderedList<HuffmanPair> pairsList) {
ArrayOrderedList<HuffmanTree> buildList = new
ArrayOrderedList<HuffmanTree>();
if (pairsList.size()
> 1) {
for (int i = 0; i < pairsList.size(); i++) {
HuffmanTree newTree = new
HuffmanTree(pairsList.getElement(i));
buildList.add(newTree);
}
while (buildList.size() > 1) {
HuffmanTree leftTree;
HuffmanTree rightTree;
leftTree = buildList.removeFirst();
rightTree = buildList.removeFirst();
int totalFreq = leftTree.getRoot().getElement().getFrequency() +
rightTree.getRoot().getElement().getFrequency();
HuffmanPair root = new HuffmanPair(totalFreq);
HuffmanTree FINALHTREE = new HuffmanTree(root, leftTree,
rightTree);
buildList.add(FINALHTREE);
}
this.setRoot(buildList.removeFirst().getRoot());
} else {
new HuffmanTree(pairsList.removeFirst());
}
}
/**
* compare method that is used by the add
method, this method ensures that the add method places node in
correct order.
* @param otherTree
* @return
*/
public int compareTo(HuffmanTree otherTree)
{
if
(otherTree.getRoot().getElement().getFrequency() >
getRoot().getElement().getFrequency()) {
return -1;
} else if
(otherTree.getRoot().getElement().getFrequency() ==
getRoot().getElement().getFrequency()) {
return 0;
} else {
return 1;
}
}
/**
* returns string representation of huffman
tree
* @return
*/
public String toString() {
String s = "";
Iterator<HuffmanPair> list;
list =
iteratorPreOrder();
while (list.hasNext())
{
s += list.next().toString();
}
return s;
}
}
HuffmanCoder.java
public class HuffmanCoder extends HuffmanTree {
private HuffmanTree huffTree;
private ArrayUnorderedList<EncodingData>
encodingList= new ArrayUnorderedList<EncodingData>();
/**
* constructor for huffman coder
* @param pairsList
*/
public
HuffmanCoder(ArrayOrderedList<HuffmanPair> pairsList){
huffTree= new
HuffmanTree(pairsList);
buildEncodingList(huffTree.getRoot(),"");
}
/**
* method to decode the code
* @param code
* @return
*/
public char decode(String code ) {
char
target=(char)0;
int i =0;
//BinaryTreeNode<HuffmanPair> node;
while (i<
encodingList.size()){
if (encodingList.getElement(i).getEncoding().equals(code)){
target=encodingList.getElement(i).getSymbol();
break;
}
else {
i++;
}
}
return target;
}
/**
* method to encode the character
* @param c
* @return
* @throws ElementNotFoundException
*/
public String encode(char c) throws
ElementNotFoundException{
int i=0;
String
target=null;
while
(i<encodingList.size()){
if (encodingList.getElement(i).equals(c)){
target=encodingList.getElement(i).getEncoding();
break;
}
else {
i++;
}
}
if (target==null){
throw new ElementNotFoundException("ELEMENT NOT FOUND");
}
return target;
}
/**
* build the encoding list
* @param node
* @param encoding
*/
private void
buildEncodingList(BinaryTreeNode<HuffmanPair> node, String
encoding){
EncodingData data = new
EncodingData(node.getElement().getCharacter(), encoding);
if
(node.isLeaf()){
encodingList.addToRear(data);
}
else {
buildEncodingList(node.getLeft(),encoding+0);
buildEncodingList(node.getRight(),encoding+1);
}
}
/**
* returns string representation of huffman
coder
* @return
*/
public String toString(){
int i=0;
String s=null;
while
(i<encodingList.size()){
s=encodingList.getElement(i)+s;
i++;
}
return s;
}
}
The file Assmt3Files contains all the classes that are provided with this assignment. Use the classes...