For this assignment, you will write a program to work with
Huffman encoding. Huffman code is an optimal prefix code, which
means no code is the prefix of another code. Most of the code is
included. You will need to extend the code to complete three
additional methods. In particular, code to actually build the
Huffman tree is provided. It uses a data file containing the
frequency of occurrence of characters. You will write the following
three methods in the HuffmanTree class:
public ArrayList getCodes();
public String encode(String str);
public String decode(String huffString);
getCodes method:
The getCodes method traverses the tree to generate a list of the
characters and their corresponding codes. You will actually be
asked to write this traverse method, which is directly called from
getCodes – it returns the Huffman code for each of the
letters:
private void traverse(ArrayList code, BinaryTreeNode
node, String prefix)
This private method requires that you recursively call it in order
to traverse the tree. Once you’ve reached your base case, you have
your Huffman Code for this letter so add it to your ArrayList!
encode method
The encode method takes a text string (lowercase and spaces
only–the driver class provided replaces all non
- lowercase letters & spaces with an empty string) and encodes
it using the Huffman encoding from the tree. It returns a binary
string representation of the encoding. Here we use a String,
computing the length of the encode string and working with ‘0’ and
‘1’ characters. The encode method can use the getCodes method to
produce a look up table, then step through the parameter string and
simply “look up” the code for each character and append the code,
made up of 0’s & 1’s, to the end of the encoded string. A
sequential search through the ArrayList for each character is fine
since there are only 27 elements in the list.
decode method:
The decode method takes a string of "0"’s and "1"’s that has been
encoded using the Huffman Tree, using the tree to decode it a back
into the original ASCII string. Keep in mind that because Huffman
code is a prefix code, you can start at the root of the Huffman
tree and traverse left for 0 and right for a 1 until a leaf is
reached. The character associated with that code (stored in the
node) can be appended to the decoded string, then reset back to the
root and continue stepping through the huffString parameter until
the end of that string is reached
Letter.java:
public class Letter {
char letter;
double frequency;
public Letter(char letter, double frequency) {
super();
this.letter = letter;
this.frequency = frequency;
}
public char getLetter() {
return letter;
}
public void setLetter(char letter) {
this.letter = letter;
}
public double getFrequency() {
return frequency;
}
public void setFrequency(double frequency) {
this.frequency = frequency;
}
@Override
public String toString() {
return "Letter [letter=" + letter +
", frequency=" + frequency + "]" + "\n";
}
}
InvalidHuffmanCodeException.java:
public class InvalidHuffmanCodeException extends
RuntimeException{
/**
* Sets up this exception with an
appropriate message.
* @param collection the name of the
collection
*/
public InvalidHuffmanCodeException()
{
super("The Huffman Code
could not be determined!");
}
}
HuffmanTreeTest.java
import static org.junit.Assert.*;
import java.util.ArrayList;
import org.junit.Test;
public class HuffmanTreeTest {
@Test
public void testcode3() {
HuffmanTree evaluator = new
HuffmanTree("letter_frequency.txt");
ArrayList<Code> codes =
evaluator.getCodes();
assertEquals("Code [ch=s,
code=11111]", codes.get(26).toString());
}
@Test
public void encode3() {
HuffmanTree evaluator = new
HuffmanTree("letter_frequency.txt");
ArrayList<Code> codes =
evaluator.getCodes();
assertEquals("00",
evaluator.encode(" "));
}
@Test
public void encode5() {
HuffmanTree evaluator = new
HuffmanTree("letter_frequency.txt");
ArrayList<Code> codes =
evaluator.getCodes();
assertEquals("1111010011101110110001000110110011011110111100010",
evaluator.encode("hotty toddy"));
}
@Test
public void encode6() {
HuffmanTree evaluator = new
HuffmanTree("letter_frequency.txt");
ArrayList<Code> codes =
evaluator.getCodes();
assertEquals("110001100111100011101001111111100110011110101000101001101011100111110101100000010011000100010010101011101111110010101000111001",
evaluator.encode("four score and seven years ago"));
}
@Test(expected =
InvalidHuffmanCodeException.class)
public void encode9() {
HuffmanTree evaluator = new
HuffmanTree("letter_frequency.txt");
ArrayList<Code> codes =
evaluator.getCodes();
String result =
evaluator.encode("");
fail("Did not catch invalid Huffman
Code Exception");
}
@Test
public void decode1() {
HuffmanTree evaluator = new
HuffmanTree("letter_frequency.txt");
ArrayList<Code> codes =
evaluator.getCodes();
assertEquals("q",
evaluator.decode("1100001011"));
}
@Test
public void decode2() {
HuffmanTree evaluator = new
HuffmanTree("letter_frequency.txt");
ArrayList<Code> codes =
evaluator.getCodes();
assertEquals("i",
evaluator.decode("0111"));
}
@Test
public void decode3() {
HuffmanTree evaluator = new
HuffmanTree("letter_frequency.txt");
ArrayList<Code> codes =
evaluator.getCodes();
assertEquals("work hard play
harder",
evaluator.decode("110010100111101110000110011110101011101101110010000110110101010001000111101010111011011101011101"));
}
}
HuffmanTree.java:
/* This HuffmanTree class has been created from a scaled down
version of
* LinkedBinaryTree class from the textbook.
*
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class HuffmanTree implements HuffmanADT
{
protected BinaryTreeNode<Letter>
root;
protected int modCount;
ArrayList<Letter> list = new
ArrayList<Letter>();
/**
* Creates a Huffman tree using the
character set and frequency distribution
* given in the file with name passed as a
parameter.
*
*/
public HuffmanTree(String filename)
{
root = null;
// Read frequency data from file to
create list of Letter objects
try {
Scanner letter_file = new Scanner (new
File(filename));
while (letter_file.hasNext()) {
String line =
letter_file.nextLine();
list.add(new
Letter(line.charAt(0),
Double.parseDouble(line.substring(2))));
}
// Construct the Huffman tree using the list of
Letters
build();
}
catch
(FileNotFoundException e) {
System.out.println("Frequency file not
found.");
System.exit(0);
}
}
private void build() {
// Make leaf
nodes in the tree/forest for each character
ArrayList<BinaryTreeNode<Letter>> nodeList = new
ArrayList<BinaryTreeNode<Letter>>();
BinaryTreeNode<Letter> temp = null;
for (int i=0;
i<list.size(); i++) {
temp = new BinaryTreeNode<Letter>(new
Letter(list.get(i).getLetter(),
list.get(i).getFrequency()));
nodeList.add(temp);
}
/* Use standard
idea of Huffman encoding to build tree from leaf nodes.
* Repeatedly,
find the two subtrees with minimum weight and join them.
* Internal nodes
don't use the "letter" field, so just make them a constant
* (#). The
frequency used for the internal node is the sum of the
frequency
* of the two
children. Stop when one node left in forest--it is a tree!
*/
BinaryTreeNode<Letter> node1, node2;
while
(nodeList.size() > 1) {
node1 = getMin(nodeList);
node2 = getMin(nodeList);
Letter internalElement = new Letter('#',
node1.getElement().getFrequency() +
node2.getElement().getFrequency());
BinaryTreeNode<Letter> internal =
new
BinaryTreeNode<Letter>(internalElement);
internal.setLeft(node1);
internal.setRight(node2);
nodeList.add(internal);
}
// The one
remaining node is the root
root =
nodeList.get(0);
}
private BinaryTreeNode<Letter>
getMin(ArrayList<BinaryTreeNode<Letter>> nodes) {
int
min=0; // index of min
//
Find the node in the forest with the least frequency
for
(int i=1; i<nodes.size(); i++) {
if
(nodes.get(i).getElement().getFrequency() <
nodes.get(min).getElement().getFrequency()) {
min = i;
}
}
//
Save, remove, then return the smallest node
BinaryTreeNode<Letter> smallest = nodes.get(min);
nodes.remove(min);
return smallest;
}
public Letter getRootElement() throws
EmptyCollectionException
{
if (root == null)
throw new EmptyCollectionException("Huffman
Tree");
else return
root.getElement();
}
protected BinaryTreeNode<Letter>
getRootNode() throws EmptyCollectionException
{
if (root == null)
throw new EmptyCollectionException("Huffman
Tree");
else return root;
}
public BinaryTreeNode<Letter>
getLeft()
{
return root.left;
}
public BinaryTreeNode<Letter>
getRight()
{
return root.right;
}
public boolean isEmpty()
{
return (root ==
null);
}
/* This method returns an ArrayList of the
codes in the Huffman Tree.
* The Code class has a character and its
corresponding encoding. In the
* tree, left edges are designated as 0 and
right edges as 1.
*
* DO NOT CHANGE THIS METHOD, but you need
to write the traverse method.
*/
public ArrayList<Code> getCodes() {
ArrayList<Code> code = new ArrayList<Code>();
if (root ==
null) return null;
traverse(code,
root.left, "0");
traverse(code,
root.right, "1");
return
code;
}
/* Recursive method to traverse the Huffman
tree, and for each leaf node,
* add a Code record to the
ArrayList.
*/
private void traverse(ArrayList<Code>
code, BinaryTreeNode<Letter> node,
String prefix) {
// TODO: Fill in
this method
}
/* The encode method can use the getCodes
method above to produce a look up
* table, then step through the parameter
string and simply "look up" the code
* for each character and append the code
to the end of the encoded string. A
* sequential search through the ArrayList
for each character is fine since
* there are only 27 elements in the
list.
*/
@Override
public String encode(String str) {
// TODO: fill in this method
return null;
}
/*
* The decode method accepts a string of
0's and 1's and uses the Huffman
* tree to determine the original string.
Because it is a prefix code, you
* can start at the root of the Huffman
tree and traverse left for 0 and right
* for a 1 until a leaf is reached. The
character associated with that code
* (stored in the node) can be appended to
the decoded string, then
* reset back to the root and continue
stepping through the huffString
* parameter until the end of that string
is reached.
*
*/
@Override
public String decode(String huffString) {
// TODO: Fill in this method
return null;
}
}
HuffmanADT.java:
import java.util.ArrayList;
public interface HuffmanADT {
public BinaryTreeNode<Letter> getLeft();
public BinaryTreeNode<Letter> getRight();
public boolean isEmpty();
public ArrayList<Code> getCodes();
public String encode(String str);
public String decode(String
huffString);
}
EmptyCollectionException.java:
/**
* Represents the situation in which a collection is empty.
*
* @author Java Foundations
* @version 4.0
*/
public class EmptyCollectionException extends
RuntimeException
{
/**
* Sets up this exception with an
appropriate message.
* @param collection the name of the
collection
*/
public EmptyCollectionException (String
collection)
{
super ("The " +
collection + " is empty.");
}
}
ElementNotFoundException.java:
/**
* ElementNotFoundException represents the situation in which a
target element
* is not present in a collection
*
* @author Java Foundations
* @version 4.0
*/
public class ElementNotFoundException extends
RuntimeException
{
/**
* Sets up this exception with an
appropriate message.
*/
public ElementNotFoundException (String
collection)
{
super ("The target element is
not in this " + collection);
}
}
Driver.java:
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class Driver {
public static void main(String[] args) throws
FileNotFoundException {
System.out.println("Start");
// Instantiate LinkedBinaryTree and
build Huffman tree from frequency file
HuffmanTree huff = new
HuffmanTree("letter_frequency.txt");
// Get the codes generated and
print table
ArrayList<Code> codes =
huff.getCodes();
System.out.println("Size of codes
is " + codes.size());
for (Code c: codes) {
System.out.println(c);
}
// Test the encoding
Scanner in = new
Scanner(System.in);
boolean done = false;
do {
System.out.print("Enter a string (END to exit) --> ");
String input =
in.nextLine();
input =
input.toLowerCase();
// Remove
everything except lowercase letters: a-z & spaces: \s
// ^ means any
character but the following...
input =
input.replaceAll("[^a-z\\s]", "");
if
(!input.equals("end")) {
// Get and display encoding of string, with
length
String encoding =
huff.encode(input);
System.out.printf("Original string length
is %d\n", input.length());
System.out.printf("Encoded string (length
%d), compressed %5.2f\n",
encoding.length(), encoding.length()/16.0); // Recall
that characters are normally 2 bytes
System.out.println(encoding);
// Get and display decoding of encoded
string
System.out.println();
System.out.println("Now we try to
reconstruct the original from the encoded string");
String original =
huff.decode(encoding);
if (original.equals(input)) {
System.out.println("It worked! String is: " + original);
}
else {
System.out.println("Oops. There was a problem. Decoded string is: "
+ original);
}
}
else done =
true;
} while (!done);
}
}
Code.java:
public class Code {
Character ch;
String code;
public Code(Character ch, String hcode) {
this.ch = ch;
this.code = hcode;
}
public Character getCh() {
return ch;
}
public void setCh(Character ch) {
this.ch = ch;
}
public String getCode() {
return code;
}
public void setCode(String hcode) {
this.code = hcode;
}
@Override
public String toString() {
return "Code [ch=" + ch + ", code="
+ code + "]";
}
}
BinaryTreeNode.java:
/**
* BinaryTreeNode represents a node in a binary tree with a left
and
* right child.
*
* @author Java Foundations
* @version 4.0
*/
public class BinaryTreeNode<T>
{
protected T element;
protected BinaryTreeNode<T> left,
right;
/**
* Creates a new tree node with the
specified data.
*
* @param obj the element that will become
a part of the new tree node
*/
public BinaryTreeNode(T obj)
{
element = obj;
left = null;
right = null;
}
/**
* Returns the number of non-null children
of this node.
*
* @return the integer number of non-null
children of this node
*/
public int numChildren()
{
int children = 0;
if (left !=
null)
children = 1 + left.numChildren();
if (right !=
null)
children = children + 1 + right.numChildren();
return
children;
}
/**
* Return the element at this node.
*
* @return the element stored at this
node
*/
public T getElement()
{
return element;
}
/**
* Return the right child of this
node.
*
* @return the right child of this
node
*/
public BinaryTreeNode<T> getRight()
{
return right;
}
/**
* Sets the right child of this node.
*
* @param node the right child of this
node
*/
public void setRight(BinaryTreeNode<T>
node)
{
right = node;
}
/**
* Return the left child of this
node.
*
* @return the left child of the node
*/
public BinaryTreeNode<T> getLeft()
{
return left;
}
/**
* Sets the left child of this node.
*
* @param node the left child of this
node
*/
public void setLeft(BinaryTreeNode<T>
node)
{
left = node;
}
}
letter_frequency.java:
20.152
a 6.5336
b 1.1936
c 2.2256
d 3.4024
e 10.1616
f 1.7824
g 1.612
h 4.8752
i 5.5728
j 0.01224
k 0.576
l 3.22
m 1.9248
n 5.3992
o 6.0056
p 1.5432
q 0.076
r 4.7896
s 5.0616
t 7.2448
u 2.2064
v 0.7824
w 1.888
x 0.12
y 1.5792
z 0.0592
Traverse, Decode and Encode methods are implemented below-
/* Recursive method to traverse the Huffman tree, and for each
leaf node,
* add a Code record to the ArrayList.
*/
private void traverse(ArrayList<Code> code,
BinaryTreeNode<Letter> node,
String prefix) {
// TODO: Fill in this method
if(node.left==null && node.right==null) {
Code c= new Code(node.getElement().getLetter(),prefix);
code.add(c);
}
else{
traverse(code,node.left,prefix+"0");
traverse(code,node.right,prefix+"1");
}
}
/* The encode method can use the getCodes method above to produce a
look up
* table, then step through the parameter string and simply "look
up" the code
* for each character and append the code to the end of the encoded
string. A
* sequential search through the ArrayList for each character is
fine since
* there are only 27 elements in the list.
*/
@Override
public String encode(String str) {
// TODO: fill in this method
String encoded="";
HuffmanTree huff = new HuffmanTree("letter_frequency.txt");
ArrayList<Code> codes = huff.getCodes();
for(int i=0;i<str.length();i++){
for (Code c: codes) {
if(c.getCh()==str.charAt(i)){
encoded+=c.getCode();
break;
}
}
}
return encoded;
}
/*
* The decode method accepts a string of 0's and 1's and uses the
Huffman
* tree to determine the original string. Because it is a prefix
code, you
* can start at the root of the Huffman tree and traverse left for 0
and right
* for a 1 until a leaf is reached. The character associated with
that code
* (stored in the node) can be appended to the decoded string,
then
* reset back to the root and continue stepping through the
huffString
* parameter until the end of that string is reached.
*
*/
@Override
public String decode(String huffString) {
// TODO: Fill in this method
BinaryTreeNode<Letter> node=root;
int count=0;
String decoded="";
int i=0;
while(count<huffString.length()){
for(i=count;i<=huffString.length();i++){
if(node.left==null && node.right==null)
{decoded+=node.getElement().getLetter(); count=i;break;}
else{
if(huffString.charAt(i)=='0') node=node.left;
else node=node.right;
}
}
node=root;
}
return decoded;
}
Output-
For this assignment, you will write a program to work with Huffman encoding. Huffman code is...
I have almost done with this code to Implement Huffman Coding. However I have an error at the "Heap<Tree>". Could anyone help with solving this issue, really appreciated. Thank you!! import java.util.Scanner; public class HuffmanEncoding { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Enter a text: "); String text = input.nextLine(); int[] counts = getCharacterFrequency(text); // Count frequency System.out.printf("%-15s%-15s%-15s%-15s\n", "ASCII Code", "Character", "Frequency", "Code"); Tree tree = getHuffmanTree(counts); // Create a Huffman tree String[]...
I am getting a seg fault with my huffman tree. I'm not sure if it's my deconstructors but also getting some memory leaks. Can some one help me find my seg fault? It's in c++, thanks! //#ifndef HUFFMAN_HPP //#define HUFFMAN_HPP #include<queue> #include<vector> #include<algorithm> #include<iostream> #include <string> #include <iostream> using namespace std; class Node { public: // constructor with left and right NULL nodes Node(char charTemp, int c) { ch = charTemp; count = c; left...
You will construct a Huffman tree based on the given frequencies of 26 English alphabets in upper case plus the space character. An internal tree node class in HuffmanTree with necessary information is required. • You will not randomly switch left and right children when merger two trees. Instead, you will build a right-heavy tree according to the following strategies to select the right child. (1) The tree that is taller will be the right child, i.e., the height is...
. Huffman Encoding (a.) (6 points) Suppose a certain file contains only the following letters with the corresponding frequencies 1 AİB 73 9 30 44 130 28 16 In a fixed-length encoding scheme, cach character is given a binary representation with the same number of bits. What is the minimum number of bits required to represent each letter of this file under fixed-length encoding scheme? Describe how to encode all seven letters in this file using the number of bits...
This is my code for family tree, but i am confused on how to make a main class that will use these methods. public class FamilyTree { private class Node { String name; Node next; Node child; public Node(String name) { this.name = name; next = null; child = null; } } public Node addSibling(Node node, String name) { if(node == null) return null; while(node.next != null) node = node.next; return(node.next = new Node(name)); } public Node addChild(Node...
In Java. How would this method look? LinkedBinaryTree.java import java.util.Iterator; public class LinkedBinaryTree implements BinaryTreeADT { private BinaryTreeNode root; /** * Creates an empty binary tree. */ public LinkedBinaryTree() { root = null; } /** * Creates a binary tree from an existing root. */ public LinkedBinaryTree(BinaryTreeNode root) { this.root = root; } /** * Creates a binary tree with the specified element...
(b.) Huffman code is a way to encode information using variable-length binary strings to represent symbols depending on the frequency of each individual letter. Specifically, letters that appear more frequently can be encoded into strings of shorter lengths, while rarer letters can be turned into longer binary strings. On average, Huffman code is a more efficient way to encode a message as the number of bits in the output string will be shorter than if a fixed-length code was used....
*Java* You will write a program to do the following: 1. Read an input file with a single line of text. Create a method named load_data. 2. Determine the frequency distribution of every symbol in the line of text. Create a method named 3. Construct the Huffman tree. 4. Create a mapping between every symbol and its corresponding Huffman code. 5. Encode the line of text using the corresponding code for every symbol. 6. Display the results on the screen....
Can you take a look at my code that why the maxDepth function is not working? public class BinaryTree { class Node{ int key; Node left,right; public Node(int item) { key = item; left = right = null; } } Node root; public void BinaryTree(){ root = null; } void...
Complete the following code: You are asked to write some functionalities for a spelling checker inside Tree.java that has at least the following methods: /*Adds a word to a spelling checker’s collection of correctly spelled words*/ void add(String word) /*Returns true if the given word is spelled correctly*/ boolean check(String word) /*Returns back all words in the tree in alphabetical order*/ public String getDictionaryInAlphabeticalOrder() Store the collection of correctly spelled words in a 26-ary tree. The number 26 indicates that...