Priority Queues with Huffman tree - java

i am trying to create a Huffman tree by reading in a file and counting the frequency of each letter space symbol etc. i'm using a Priorityqueue to queue the items from smallest to largest but when i insert them into the queue they dont queue correctly here is my code.
package huffman;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Scanner;
public class Huffman {
public ArrayList<Frequency> fileReader(String file)
{
ArrayList<Frequency> al = new ArrayList<Frequency>();
Scanner s;
try {
s = new Scanner(new FileReader(file)).useDelimiter("");
while (s.hasNext())
{
boolean found = false;
int i = 0;
String temp = s.next();
while(!found)
{
if(al.size() == i && !found)
{
found = true;
al.add(new Frequency(temp, 1));
}
else if(temp.equals(al.get(i).getString()))
{
int tempNum = al.get(i).getFreq() + 1;
al.get(i).setFreq(tempNum);
found = true;
}
i++;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return al;
}
public void buildTree(ArrayList<Frequency> al)
{
PriorityQueue<Frequency> pq = new PriorityQueue<Frequency>();
for(int i = 0; i < al.size(); i++)
{
pq.add(al.get(i));
}
while(pq.size() > 0)
{
System.out.println(pq.remove().getString());
}
}
public void printFreq(ArrayList<Frequency> al)
{
for(int i = 0; i < al.size(); i++)
{
System.out.println(al.get(i).getString() + "; " + al.get(i).getFreq());
}
}
}
in the buildTree() method is where im having the problem. what im trying to do is queue Frequency objects which holds the letter/space/symbol and the frequency as an int the frequency class is this.
public class Frequency implements Comparable {
private String s;
private int n;
Frequency(String s, int n)
{
this.s = s;
this.n = n;
}
public String getString()
{
return s;
}
public int getFreq()
{
return n;
}
public void setFreq(int n)
{
this.n = n;
}
#Override
public int compareTo(Object arg0) {
// TODO Auto-generated method stub
return 0;
}
}
how can i get the priorityqueue to use the frequency number to queue them from smallest to biggest?

Actually you missed to implement the compareTo method to make your object effectively comparable.
The compareTo method, as documentation states, should
return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
This means that in your case you should do something like:
public int compareTo(Object arg0)
{
Frequency other = (Frequency)arg0;
return n < other.n ? -1 : (n == other.n ? 0 : 1);
}
But mind that comparable has a generic type that is preferable: Comparable<T> so you can avoid the cast on arg0 to make it a Frequency object with static type safety too:
class Frequency implements Comparable<Frequency> {
public int compareTo(Frequency f2) {
// directly compare
}
}

I think that "Auto-generated method stub" needs to be filled in with a real implementation of a "compareTo" so as to satisfy the requirements for something to be Comparable, which I assume the PriorityQueue is going to rely upon. The implementation is probably going to be "n < arg0", with appropriate downcasting from Object.

A Priority Queue, just as a data structure, is based on the concept of an ordering - you use such a structure when you want to order elements in a certain way - which elements are more important than others, etc.
In Java, ordering objects is usually done in one of two ways - your objects implement the Comparable interface, or you supply a Comparator<E> which knows how to order objects of type E.
To determine which object is "more important" than another, the compareTo() method is invoked. This method has a pretty simple contract:
Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
Your implementation of Frequency.compareTo() always returns 0 for the comparison. Thus, you are specifying that all Frequency objects are equal to any other Frequency objects. This is clearly not what you want.

Related

The use of relational operator inside binarySearch() method which is a generics is giving error.How to handle this situation?

Here's my java code and the problem is that the use of relational
operator(<) inside binarySearch() is giving error.
I guess this error I am getting because the operands are of type object.
How to remove this error so my function runs perfectly?
import java.util.Random;
import java.util.Arrays;
class BinarySearch
{
public static void main(String $[])
{
Integer arr[]=new Integer[20];
for(int i=0;i<20;i++)
arr[i]=(new Random()).nextInt()%10000;
display("Initial array :\n");
array(arr);
Arrays.sort(arr);
display("After sorting :\n");
array(arr);
display("Enter the element to be searched for : ");
Integer elem=(new java.util.Scanner(System.in)).nextInt();
display(elem+(binarySearch(arr,elem)?" Found":" Not found")+"\n");
}
public static <T>boolean binarySearch(T arr[],T val)
{
int start=0;
int end=arr.length-1;
while(start<=end)
{
int mid=(start+end)/2;
if(arr[mid]==val)
return true;
if(arr[mid]<val)
start=mid+1;
else
end=mid-1;
}
return false;
}
public static void display(Object o)
{
System.out.print(o);
}
public static <T>void array(T arr[])
{
for(int i=0;i<arr.length;i++)
display(arr[i]+" ");
display("\n");
}
}
The problem is that your binarySearch() method is accepting parameters that will be Objects rather than primitive types, so it is unwise to compare them using the equality operator == and invalid to compare them using the less than operator <. Instead define your binarySearch method as follows:
public static <T extends Comparable<T>> boolean binarySearch(T arr[],T val) {
int start = 0;
int end = arr.length-1;
while(start <= end) {
int mid=(start+end)/2;
int comparison = arr[mid].compareTo(val);
if(comparison == 0) {
return true;
}
if(comparison < 0) {
start = mid+1;
}
else {
end = mid-1;
}
}
return false;
}
Read here about generics. Since all generics are objects - you can't use comparison operators with them. Even if you type <T extends Number.
There are two ways to handle this:
Pass Comparator<T> to the method and use comparator.compare(arr[mid], val) for comparing values.
Write <T extends Comparable> and call arr[mid].compareTo(val).
Both these methods return an integer value:
0, if values are equal
negative, if first value less than second
positive, if first value greater than second

I'm getting some errors when I try to implement a generic datatype to my class

I've been trying to search, but I can't quite find the answer to my problem. I feel like I've implemented my generic datatype correctly but I'm still getting an error.
I'm doing an exercise where I'm given constructors/methods and variables (so I can't change the variable inputs for instance), and now I have to write the constructors/methods to make them work. The program creates an array (objects) that can grow by adding elements to it, and the comments above each method in the code explains what they do.
When I try to create the arrays in my two constructors, I get the error "Variable must provide either dimension expressions or an array initializer" for the empty array and "Type mismatch: cannot convert from T[] to int".
In my "add" method I get the error "Cannot invoke add(int, T) on the array type T[]" and finally in my "toArray" method I get the error "Type mismatch: cannot convert from Object[] to T[]".
The common theme seems to be that I haven't implemented the generic datatype correctly, but no matter how many times I try to search for similar questions, I can't see how what I've done have been different.
When searching, I see many people say that an array can't "grow" and to instead use an ArrayList, however there has to be a way to solve this with just an array, otherwise you can't solve this exercise.
import java.util.ArrayList;
import java.util.Arrays;
public class GrowingArray<T> {
private Object[] objects;
private int pointer;
//empty array
public GrowingArray() {
objects = new Object[];
}
//array that contains ds
public GrowingArray(T[] ds) {
objects = new Object[ds];
}
// add element e and return true
public boolean add(T e) {
pointer = 0;
objects.add(pointer++, e);
return true;
}
// return true if value d is found in the array
public boolean contains(T d) {
for(int i = 0; i <= objects.length; i++) {
if(objects[i] == d) {
}
}
return true;
}
// return the element on index i
public T get(int index) {
int i = index;
return objects[i];
}
// return first index containing d, if not found return -1
public int indexOf(T d) {
for(int i = 0; i <= objects.length; i++) {
if(d == objects[i]) {
return i;
}
}
return -1;
}
// return last index containing d, if not found return -1
public int lastIndexOf(T d) {
for(int i = objects.length; i >= 0; i--) {
if(d == objects[i]) {
return i;
}
}
return -1;
}
// return length of array
public int size() {
return objects.length;
}
// return a trimmed version of the array
public T[] toArray() {
return Arrays.copyOf(objects, objects.length);
}
}
objects = new Object[];
"Variable must provide either dimension expressions or an array initializer"
You need to pass a size. Empty brackets don't work.
objects = new Object[someInitialSize];
objects = new Object[ds];
"Type mismatch: cannot convert from T[] to int"
To copy an array use Arrays.copyOf:
objects = Arrays.copyOf(ds, ds.length);

How to decide the state of an object before starting to code?

I have the following code for displaying the sum of two consecutive element of ArrayList until the element left is one.for example:-
if i entered
1 2 3 4 5
output
3 7 5 //adding the two consecutive last one is as it is
10 5//doing the same thing
15
code
import java.util.*;
import java.lang.Integer;
class Substan{
ArrayList <Integer> list = new ArrayList <Integer> ();
ArrayList <Integer> newList = new ArrayList <Integer> ();// this will be the list containing the next sequence.
int index=0;
int sum=0;
Substan(){
Scanner read = new Scanner(System.in);
String choice;
System.out.println("Enter the elements of the array");
do{
int element = read.nextInt();
list.add(element);
System.out.println("More?");
choice = read.next();
}while(choice.equals("y") || choice.equals("Y"));
}
/* precondition- we have the raw list that user has enterd.
postcondition - we have displayed all the sublists,by adding two consecutives numbers and the last one is having one element.
*/
void sublist(){
while(noofElementsIsNotOneInList()){
index =0;
while(newListIsNotComplete()){
if(nextElementIsThere()){
sum = addTheConsecutive();
}
else{
sum = getLastNumber();
}
storeSumInNewList();
}
displayTheNewList();
System.out.println("");
updateTheLists();
}
displayTheNewList(); //as we have danger of Off By One Bug (OBOB)
System.out.println("");
}
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
private boolean newListIsNotComplete(){
boolean isNotComplete = true;
int listSize = list.size();
int newListSize = newList.size();
if (listSizeIsEven()){
if ( newListSize == listSize/2){
isNotComplete = false;
}
}
else{
if( newListSize == (listSize/2) +1){
isNotComplete = false;
}
}
return isNotComplete;
}
private boolean listSizeIsEven(){
if ( list.size()%2 == 0 ){
return true;
}
else{
return false;
}
}
/*
we are at some index.
returns true if we have an element at (index+1) index.
*/
private boolean nextElementIsThere(){
if ( list.size() == index+1 ){
return false;
}
else{
return true;
}
}
/* precondition-we are at index i
postcondition - we will be at index i+2 and we return sum of elements at index i and i+1.
*/
private int addTheConsecutive(){
int sum = list.get(index)+list.get(index+1);
index += 2;
return sum;
}
/* we are at last element and we have to return that element.
*/
private int getLastNumber(){
return list.get(index);
}
private void storeSumInNewList(){
newList.add(sum);
}
private void displayTheNewList(){
int size = newList.size();
for ( int i=0;i<size;i++){
System.out.print(newList.get(i)+" ");
}
}
/*precondition - we have processed all the elements in the list and added the result in newList.
postcondition - Now my list will be the newList,as we are processing in terms of list and newList reference will have a new object.
*/
private void updateTheLists(){
list = newList;
newList = new ArrayList <Integer>();// changing the newList
}
public static void main(String[] args) {
Substan s = new Substan();
s.sublist();
}
}
So i have done a lot of refinement of my code but having a problem of sharing the local variables with the other methods.for example i have used index instance for storing the index and initially i thought that i will put this as not an instance but a local variable in method sublist() but as it cannot be viewed from other methods which needed to use the index like addTheConsecutive().So considering that i put the index at class level.So is it wright approach that put the variables that are shared at class level rather than looking at only the state of the object initially before coding and stick to that and never change it?
Consider this:
An object can communicate with other(s) only by sharing its attributes. So, if you need an object to read the state of another, the only way it can be done is by giving it "permission" to read the other object attributes.
You have two ways to do that:
Declaring the object attributes public, or
Creating getXXX() methods (makes sense for private attributes)
I personally prefer option two, because the getXXX() method returns the value ("state") of a particular attribute without the risk of being modified. Of course, if you need to modify a private attribute, you should also write a setXXX() method.
Example:
public class MyClass {
private int foo;
private String bar;
/*
* Code
*/
public int getFoo() {
return foo;
}
public String getBar() {
return bar;
}
public void setFoo(int foo) {
this.foo = foo;
}
public void setBar(String bar) {
this.bar = bar;
}
/*
* More code
*/
}
This way all the object attributes are encapsulated, and:
they cannot be read by any other object, unless you specifically call the appropriate getXXX() function, and
cannot be altered by other objects, unless you specifically call the appropriate setXXX() function.
Compare it with the non-abstracted version.
for (int index = 0; index < list.size(); index += 2) {
int sum = list.get(index);
if (index + 1 < list.size() {
sum += list.get(index + 1);
}
newList.add(sum);
}
Now, top-down refining the algorithm using names is a sound methodology, which helps in further creative programming.
As can seen, when abstracting the above again:
while (stillNumbersToProcess()) {
int sum = sumUpto2Numbers();
storeSumInNewList(sum);
}
One may keep many variables like sum as local variables, simplifying state.
One kind of helpful abstraction is the usage of conditions, in a more immediate form:
private boolean listSizeIsEven() {
return list.size() % 2 == 0;
}
private boolean nextElementIsThere() {
return index + 1 < list.size();
}
There's no point in declaring index at Class level since you dont want it to be a member or an instance of that class. Instead make it local to the method and pass it to other methods as argument where you want to access it.
I think you are asking the wrong question.
Your class variables make very little sense, as do many of the methods. This is mostly because:
Your class is doing too much
Your algorithm is a little odd
The class variables that you do have make much more sense passed as method parameters. Some methods need to see them, and some don't.
Your class is also a little odd, in that calling subList twice on the same class will not produce the same answer.
The code is littered with methods I don't quite see the point in, such as:
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
Shouldn't this be:
private boolean noofElementsIsNotOneInList(){
return list.size() == 1;
}
And it makes no sense for it to use some arbitrary List, pass one in so that you know which List you are checking:
private boolean noofElementsIsNotOneInList(final Collection<?> toCheck){
return toCheck.size() == 1;
}
The same logic can be applied to almost all of your methods.
This will remove the instance variables and make your code much more readable.
TL;DR: Using lots of short appropriately named methods: good. Having those methods do things that one wouldn't expect: bad. Having lots of redundant code that makes things very hard to read: bad.
In fact, just to prove a point, the whole class (apart from the logic to read from stdin, which shouldn't be there anyway) can transformed into one short, recursive, method that requires no instance variables at all:
public static int sumPairs(final List<Integer> list) {
if (list.size() == 1)
return list.get(0);
final List<Integer> compacted = new LinkedList<>();
final Iterator<Integer> iter = list.iterator();
while (iter.hasNext()) {
final int first = iter.next();
if (iter.hasNext()) compacted.add(first + iter.next());
else compacted.add(first);
}
return sumPairs(compacted);
}
Now you could break this method apart into several appropriately named shorter methods, and that would make sense. It's sometimes more helpful to start from the other end. Sketch out the logic of your code and what it's trying to do, then find meaningful fragments to split it into. Possibly after adding unit tests to verify behaviour.
what about doing by Recursion:
public int calculateSum(List<Integer> nums) {
displayList(nums);
if (nums.size() == 1) {
return nums.get(0);
}
List<Integer> interim = new ArrayList<Integer>();
for (int i = 0; i < nums.size(); i = i + 2) {
if (i + 1 < nums.size()) {
interim.add(nums.get(i) + nums.get(i + 1));
} else {
interim.add(nums.get(i));
}
}
return calculateSum(interim);
}
public static void displayList(List<Integer> nums){
System.out.println(nums);
}
Steps:
Run calculate sum until list has 1 element
if list has more than 1 element:
iterate the list by step +2 and sum the element and put into a new List
again call calculate sum

hashCode collisions are putting two different words in same position

I am supposed to implement an interface with a hash table. Problem is that I'm getting the wrong output and it's due to collision (from what I understand). I haven't been writing this code completely solo, I've been getting help. I'm not a master at Java, very early in my course so this is all very hard for me so please be patient.
Here is my code so far:
runStringDictionary.java
import java.io.BufferedReader;
import java.io.FileReader;
public class runStringDictionary {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
if (args.length == 0 || args.length > 1) {
System.out.println("Syntax to run the program: java runStringDictionary <inputFile>");
}
if (args.length == 1) {
try {
Dictionary myDictionary = new Dictionary(); //Initialize a Dictionary to store input words
BufferedReader br = new BufferedReader(new FileReader(args[0])); //Read the text file input
String line;
while ((line = br.readLine()) != null) {//Read each line
String[] strArray = line.split(" "); //Separate each word in the line and store in another Array
for (int i = 0; i < strArray.length; i++) { //Loop over the Array
if (myDictionary.contains(strArray[i])) { //Check if word exists in the dictionary
myDictionary.remove(strArray[i]); //if it does remove it
} else {
myDictionary.add(strArray[i]); //if it doesn't then add it
}
}
}//while loop ends
//print the contents of myDictionary
for (int i = 0; i < 25; i++) {
if (myDictionary.table[i] != null) {
System.out.println(myDictionary.table[i]);
}
}
} catch (Exception e) {
System.out.println("Error found : " + e);
}
}
}
}
StringDictionary.java
public interface StringDictionary {
public boolean add(String s);
public boolean remove(String s);
public boolean contains(String s);
}
Dictionary.java
public class Dictionary implements StringDictionary {
private int tableSize = 25;
Object[] table;
// constructor
Dictionary() {
this.table = new Object[this.tableSize];
}
#Override
public boolean add(String s) {
// TODO Auto-generated method stub
int hashCode = s.hashCode() % this.tableSize;
if (!this.contains(s)) {
this.table[hashCode] = s;
}
return false;
}
#Override
public boolean remove(String s) {
// TODO Auto-generated method stub
int hashCode = s.hashCode() % this.tableSize;
if (this.contains(s)) {
this.table[hashCode] = null;
return true;
}
return false;
}
#Override
public boolean contains(String s) {
// TODO Auto-generated method stub
int hashCode = s.hashCode() % this.tableSize;
if (table[hashCode] != null) {
if (table[hashCode].equals(s))
return true;
}
return false;
}
}
Hashcode collisions are expected and normal; the hashcode is used to narrow down the pool of potential matches and those potential matches must then be checked for canonical equality.
This int hashCode = s.hashCode() % this.tableSize; says that your Dictionary can contain only 25 elements. For any string you'll get a hashCode from 0 to 24.
You need to keep an array of lists. Each list contains string with the same hasCode.
Hash code collisions are normal in hash tables, you would have to have a perfect hash function in order to avoid them. There are multiple strategies, that you can implement in order to deal with collisions, but basically, either you move items around in the list, placing them to different buckets, or you allow each bucket to store multiple values, such as through ArrayList.
Deciding, which value to retrieve from the table, if multiple values share the same hash code brings additional cost in terms of lookup time, therefore a good hash function will minimise the number of collisions as much as possible.
int hashCode = s.hashCode() % this.tableSize; will
You are bound to get collisions here. Valid indices into table run from 0 to this.tableSize - 1, which in your case is 24.
Hashcode collisions are expected and are a normal occurrence. Having the same hash code doesn't mean that the elements are equal; it just means that they hash to the same value. You have to look at the contents to be sure.
The aim in a structure like this is usually to create a hash function that reduces the probability of collisions. You currently have a very simple hashing function that is simply the modulus of the hash code with the size of your table, and so you have a 1 / tableSize chance of a collision (someone please correct me here if I am wrong).

Is String not considered an object?

What I do not understand is why I am getting an error compiling my code when a String is in fact an object, and the compiler is saying otherwise. I dont know why I keep getting this error message
symbol: method compareTo(Object)
location: variable least of type Object
.\DataSet.java:17: error: cannot find symbol
else if(maximum.compareTo(x) < 0)
here is the code. I'm trying to utilize the class comparable to allow two objects to use the compareTo method. In the tester, I'm just trying to use a basic string object to compare.
public class DataSetTester
{
public static void main(String[] args)
{
DataSet ds = new DataSet();
String man = "dog";
String woman = "cat";
ds.add(man);
ds.add(woman);
System.out.println("Maximum Word: " + ds.getMaximum());
}
}
Class:
public class DataSet implements Comparable
{
private Object maximum;
private Object least;
private int count;
private int answer;
public void add(Object x)
{
if(count == 0){
least = x;
maximum = x;
}
else if(least.compareTo(x) > 0)
least = x;
else if(maximum.compareTo(x) < 0)
maximum = x;
count++;
}
public int compareTo(Object anObject)
{
return this.compareTo(anObject);
}
public Object getMaximum()
{
return maximum;
}
public Object getLeast()
{
return least;
}
}
Comparable Interface:
public interface Comparable
{
public int compareTo(Object anObject);
}
Of course String is an Object.
Comparable is generic now. Why do you feel the need to make those references Object if they are type String? Your code is poor; it's not a Java problem.
I don't see why DataSet needs to implement Comparable. You just need to compare incoming Strings as they're added. Do it this way and you'll fare better:
public class DataSet {
private String maximum;
private String least;
private int count;
private int answer;
public void add(String x) {
if(count == 0){
least = x;
maximum = x;
} else if (least.compareTo(x) > 0) {
least = x;
} else if(maximum.compareTo(x) < 0) {
maximum = x;
}
count++;
}
public String getMaximum() { return this.maximum; }
public String getLeast() { return this.least; }
public int getCount() { return this.count; }
}
The problem is that DataSet implements Comparable, but Object doesn't.
Instead of storing Objects, you want to store Comparables. However, if you do get this to compile, you will get into an infinite loop right here:
public int compareTo(Object anObject)
{
// Yeah, never stop loopin'!
return this.compareTo(anObject);
}
It's recommended that in newer code, you use the generic Comparable<T> interface. Your code would then look like this:
public class DataSet implements Comparable<DataSet>
{
private String maximum;
private String least;
private int count;
private int answer;
public void add(String x)
{
if(count == 0){
least = x;
maximum = x;
}
else if(least.compareTo(x) > 0)
least = x;
else if(maximum.compareTo(x) < 0)
maximum = x;
count++;
}
public int compareTo(DataSet anObject)
{
// I don't really know how you want this to work.
// Come up with your own criteria on what makes a DataSet greater or less than
// another one.
count - anObject.count
}
// Good practice to include this if you're doing a compareTo.
#Override
public boolean equals(Object other)
{
return (other instanceof DataSet) && compareTo((DataSet)other) == 0;
}
public String getMaximum()
{
return maximum;
}
public String getLeast()
{
return least;
}
}
Edit - just saw that you're comparing strings. In that case, you don't really need DataSet to implement Comparable. However, if you do need it for something else, what I wrote still stands.
least and maximum are simply Objects, and the Object class doesn't have a compareTo(...) method, simple as that. least and maximum need to be declared Comparable, not Object. And as written, it makes no sense declaring DataSet to implement the Comparable interface since there are no DataSet objects present and certainly none being compared.
java.lang.Object does not have a compareTo() method.
First of all there is an infinite loop in you code:
public int compareTo(Object anObject)
{
return this.compareTo(anObject);
}
this method is continuously calling itself.
Regarding your compile error: you have declared variable as Object, which obviously does not have a compareTo method.
There is no compareTo() method in Object. I guess you're looking for String.compareTo().
Type checking is done at compile time and not runtime. At compile time, least and maximum are considered to be objects of type Object and not String.

Categories

Resources