Comparing attribute of an object in implementation of priority queue - java

I've attempted to implement a priority queue using an Array of Objects "Queue Items" which have some data (a string), and an integer which is the priority. I am trying to make those items comparable so that when I add a new object to the queue I can iterate through the items and add the new item in the correct location and move all items that are now behind it backwards, however when I add a new item to the queue I get a null pointer exception. I'll include all my code, but the toString method was just copied in from a queue so it won't work as expected.
class QueueItem implements Comparable<QueueItem> {
String data;
int pri;
public QueueItem(String data, int pri) {
this.data = data;
this.pri = pri;
}
#Override
public int compareTo(QueueItem item) {
return this.data.compareTo(item.data);
}
}
public class PriorityQueue implements Queue<String> {
private QueueItem[] arr;
private int frontPos, backPos;
public PriorityQueue() {
arr = new QueueItem[20];
backPos = -1;
frontPos = 0;
}
public boolean isEmpty() {
return frontPos == (backPos + 1) % arr.length;
}
public String front() {
if (frontPos == (backPos + 1) % arr.length)
throw new QueueException("Empty Queue - front");
return arr[frontPos].data;
}
public int frontPri() {
if (frontPos == (backPos + 1) % arr.length)
throw new QueueException("Empty Queue - frontPri");
return arr[frontPos].pri;
}
public void addToPQ(String str, int x) {
if (arr.length==0) {
arr[frontPos] = new QueueItem(str, x);
frontPos++;
return;
}
else {
for (int i = 0; i < arr.length; i++) {
arr[i].compareTo(new QueueItem(str, x));
}
}
}
public void deleteFront() {
if (frontPos==(backPos+1)%arr.length) {
throw new QueueException("Empty Queue - deleteFront");
}
frontPos = (frontPos+1)%arr.length;
}
public String toString() {
if (frontPos == (backPos + 1) % arr.length) {
return "<>";
}
StringBuffer sb = new StringBuffer();
sb.append('<');
int pos = frontPos;
while (pos != backPos) {
sb.append(arr[pos]);
sb.append(',');
pos = (pos + 1) % arr.length;
}
sb.append(arr[backPos]);
sb.append('>');
return (sb.toString());
}
}
public interface Queue<String> {
public void addToPQ(String str, int x);
public void deleteFront();
public String front();
public boolean isEmpty();
public int frontPri();
}
class QueueException extends RuntimeException {
QueueException(String s) {
super("Tried to apply " + s + " to empty queue");
}
}
public class pqTest {
public static void main(String[] args) {
PriorityQueue pQ = new PriorityQueue();
if (pQ.isEmpty()) {
System.out.println("Queue is Empty - isEmpty");
}
pQ.addToPQ("Dog", 4);
pQ.addToPQ("Cat", 20);
pQ.deleteFront();
pQ.addToPQ("Fish", 2);
}
}

The problem is that arr is size 20 so the first element won't even be added through the if statement in your addToPQ method because arr.length != 0. So it will then go to your else statement, which iterates through every single element in arr. But arr has 20 null elements since each spot within the array of QueueItems has not been initialized. So you should change your condition in the if statement to frontPos == 0 and change the terminating condition in your loop to i < frontPos so that the method won't iterate through null elements within arr
public void addToPQ(String str, int x) {
if (frontPos==0) {
arr[frontPos] = new QueueItem(str, x);
frontPos++;
return;
}
else {
QueueItem item = new QueueItem(str, x);
for (int i = 0; i < frontPos; i++) {
arr[i].compareTo(item);
}
}
}

You get NullPointerException, because when you are adding second item, you go to else statment where you iterate over array with one non-null element and 19 nulls. So you need to change your code to check if array element at i is null and if it is, assign new element to it.

Related

The for each loop for the custom data type (ArrayList) with self implemented iterator does not run

import java.util.Arrays;
import java.util.Iterator;
public class ArrayList<Type> implements Iterable<Type> {
Type[] arr = (Type[]) new Object[10];
int size = 0;
//change capacity
public void newCapacity(int i) {
if (i == 0) {
int newIncreasedCapacity = arr.length * 2;
arr = Arrays.copyOf(arr, newIncreasedCapacity);
} else if (i == 1) {
int newDecreasedCapacity = arr.length / 2;
arr = Arrays.copyOf(arr, newDecreasedCapacity);
}
}
// add an item
public void add(Type item) {
if (size == arr.length) {
newCapacity(0);
}
arr[size++] = item; //increases size after appending
}
//remove an item
public Type remove(int index) {
if (size <= arr.length / 4) {
newCapacity(1);
}
Type removedItem = (Type) arr[index];
for (int i = index; i < size - 1; i++) {
arr[i] = arr[i + 1];
}
size -= 1;
return removedItem;
}
public int size() {
int count = 0;
for (int i = 0; i < size; i++) {
count += 1;
}
return count;
}
#Override
public Iterator<Type> iterator() {
return new ArrayIterator(arr);
}
class ArrayIterator<Type> implements Iterator<Type> {
private Type[] arrayList;
public ArrayIterator(Type[] newArray) {
arrayList = newArray;
}
// check if next element not null
public boolean hasNext() {
return (arrayList[size + 1] != null);
}
// next element
public Type next() {
if (arrayList[size + 1] != null) {
return (arrayList[size + 1]);
} else {
return null;
}
}
}
// Main Method
public static void main(String[] args) {
ArrayList<Integer> new_arr = new ArrayList<>();
new_arr.add(5);
new_arr.add(7);
new_arr.add(9);
new_arr.remove(0);
System.out.println(new_arr.size());
for (int i : new_arr) {
System.out.println(new_arr.size());
System.out.println(i);
}
}
}
I implemented the code for a custom ArrayList and also implemented an iterator for my custom data type, but I am facing an issue.
So when i run the for each loop in the main method, the loop does not run and thus nothing is printed on the console.I have checked the array which is being used for the for-each loop is not empty.Please help!
I think that you should fix your Iterator to something like
class ArrayIterator<Type> implements Iterator<Type> {
private Type[] arrayList;
private int position;
public ArrayIterator(Type[] newArray) {
arrayList = newArray;
position = 0;
}
// check if next element not null
public boolean hasNext() {
return (position != size);
}
// next element
public Type next() {
if (arrayList[position] != null) {
return (arrayList[position++]);
} else {
return null;
}
}
}
You are using the position of the size of the array to calculate the next() and hasNext(), the hasNext() is always returning null.

How to create a grab method in Java that deals with Generics and Arrays

So, I am creating a generic data structure named "Sack". In this, I add items to a sack, grab a random item, see if it's empty, or dump out its contents etc. Also, I'm creating it to expand to hold as many items as needed.
I need to create a grab method that should randomly remove and return an item from the sack. If no items are present, it should return null.
My code is the following:
public class Sack<E>
{
public static final int DEFAULT_CAPACITY = 10;
private E [] elementData;
private int size;
#SuppressWarnings("unchecked")
public Sack()
{
elementData = (E[]) new Object[DEFAULT_CAPACITY];
}
#SuppressWarnings("unchecked")
public Sack(int capacity)
{
if(capacity < 0)
{
throw new IllegalArgumentException("capacity " + capacity);
}
this.elementData = (E[]) new Object[capacity];
}
public boolean isEmpty()
{
if(size == 0)
{
return true;
}
else
{
return false;
}
}
public void add(E item)
{
int index = size++;
if(size >= elementData.length-1)
{
elementData = Arrays.copyOf(elementData, size);
}
elementData[index] = item;
}
public E [] dump()
{
E [] E2 = Arrays.copyOf(elementData, size);
for(int i = 0; i < size; i++)
{
elementData[i] = null;
}
size = 0;
return E2;
}
My grab method is right here.
public E [] grab()
{
E [] E2 = Arrays.copyOf(elementData, size);
return elementData;
}
It is incorrect, I receive an error when I run my tests stating AssertionFailedError: grab is not working correctly (check with empty sack)
==>
Expected: null
Actual : [Ljava.lang.Object;#76908cc0
My tests are right here, I cannot modify my tests, only the code provided as there is an error there, I need help on what I previously stated:
the grab method should randomly remove and return an item from the sack. If no items are
present, it should return null
Therefore, here are my tests:
#Test
public void testGrab()
{
assertNull(s.grab(), "grab is not working correctly (check with empty sack)");
Random rand = new Random();
int numElements = rand.nextInt(9) + 1;
Integer[] setElementData = new Integer[10];
ArrayList<Integer> expectedElements = new ArrayList<Integer>();
int randElement;
for(int i=0; i<numElements; ++i) {
randElement = rand.nextInt(50) + 1;
if(!expectedElements.contains(randElement)) {
setElementData[i] = randElement;
expectedElements.add(randElement);
} else {
--i;
}
}
try {
elementData.set(s, setElementData);
size.set(s, numElements);
for(int i=0; i<numElements; ++i) {
expectedElements.remove(s.grab());
assertEquals(numElements-i-1, size.get(s), "grab is not working correctly (check size usage)");
}
assertEquals(0, expectedElements.size(), "grab is not working correctly (check size usage)");
} catch (Exception e) {
fail("grab is not working correctly");
}
}
Let me know if you have any solutions for my grab method on how to accomplish this task.
I don't understand why your grab method returns an array instead of a single element. I can suggest you a different approach
public class Sack<E> {
private final static int DEFAULT_CAPACITY = 10;
private final static float REALLOC_FACTOR = 1.5f;
private E[] elementData;
private int size;
public Sack() {
this(DEFAULT_CAPACITY);
}
#SuppressWarnings("unchecked")
public Sack(int capacity) {
if(capacity <= 0)
throw new IllegalArgumentException("capacity " + capacity);
elementData = (E[]) new Object[capacity];
}
public boolean isEmpty() {
return size == 0;
}
public void add(E item) {
int index = size++;
if(size > elementData.length-1)
elementData = Arrays.copyOf(elementData, (int)(size*REALLOC_FACTOR));
elementData[index] = item;
}
public E [] dump() {
E [] E2 = Arrays.copyOf(elementData, size);
Arrays.fill(elementData, null);
size = 0;
return E2;
}
public E grab() {
if(size == 0)
return null;
int index = (int)(Math.random()*size);
E element = elementData[index];
elementData[index] = elementData[size-1];
elementData[size-1] = null;
size--;
return element;
}
}
The idea behind this grab method is to select a random index rand (from 0 to effectiveSize-1) and to return this element, but before we have to swap this element with the last element (the element with index effectiveSize-1) and reduce the effective size. I have used Math.rand() because when it is first called, it creates a single new pseudorandom-number generator and then this generator is used thereafter for all calls to this method.
Note: I've also added a realloc factor to avoid the array realloc for each element, after the array is saturated.
Here is the answer broken down a little more simply. I give credit to #Mirko Alicastro.
public E grab()
{
if(size == 0)
return null;
int index = (int) (Math.random() * size);
E element = elementData[index];
elementData[index] = elementData[size - 1];
elementData[size - 1] = null;
size--;
return element;
}
Here's another way of solving this method,
public E grab()
{
if(isEmpty())
{
return null;
}
Random rand = new Random();
int i = rand.nextInt(size);
E item = elementData[i];
remove(i);
return item;
}

What is the problem with my code , I am trying to search in the stack with an internall and external method

Write a method to find the position of a given element in a stack counting from the top of the stack. More precisely,
the method should return 0 if the element occurs on the top, 1 if there is another element on top of it, and so on. If
the element occurs several times, the topmost position should be returned. If the element doesn’t occur at all, -1
must be returned.
You are asked to write this method in two different ways; one way is to implement it internally inside the
ArrayStack class and the other way is to implement it externally in a separate class. Important: At the end
the stack should be returned to the original state (i.e. no elements should be removed and the order of the elements
should not change).
This is the externall class
public class Stack{
public static int searchstack(ArrayStack z, int n) {
ArrayStack temp = new ArrayStack(z.size());
int c = 0;
boolean flag = false;
while (!z.isEmpty()) {
if (z.top() == n) {
flag = true;
return c;
}
if (z.top() != n) {
temp.push(z.pop());
c++;
flag = false;
}
}
if (flag == false) {
c = -1;
}
while (!temp.isEmpty() && !z.isFull()) {
z.push(temp.pop());
}
return c;
}
public static void main(String[] args) {
ArrayStack z = new ArrayStack(4);
z.push(3); // first element
z.push(7);// 2nd
z.push(8);// 3rd
z.push(1);// 4th
z.printStack();
int n = 3;
System.out.println("Searching externally for" + " " + n + " " + searchstack(z, n));
System.out.println("Searching internally for" +" "+n+" "+ z.searchfor(n)+" "); //THE ERROR IS HERE
}
}
And this is the ArrayClass
public class ArrayStack {
private int[] theStack;
private int maxSize;
private int top;
public ArrayStack(int s) {
maxSize = s;
theStack = new int[maxSize];
top = -1;
}
public void push(int elem) {
top++;
theStack[top] = elem;
}
public int pop() {
int result = theStack[top];
top--;
return result;
}
public int top() {
return theStack[top];
}
public boolean isFull() {
return (top == (maxSize - 1));
}
public boolean isEmpty() {
return (top == -1);
}
public int size() {
return (top + 1);
}
//HERE IS THE METHOD I IMPLEMENTED INTERNALLY AND CALL IT AT THE STACK CLASS
public int searchfor(int n) {
for (int i = top; i >= 0; i--) {
if (theStack[top] == n) {
return i;
}
}
return -1;
}
public void printStack() {
if (top == -1)
System.out.println("Stack is empty!!\n");
else {
System.out.println(theStack[top] + " <- top");
for (int i = top - 1; i >= 0; i--)
System.out.println(theStack[i]);
System.out.println();
}
}
}
The error appearing at the Stack class is at the last line of calling the searchfor method implemented in the Arraystack class , error says that there is no method implemented in Arraystack with the name searchfor (); thiugh I did implement it .whatseems to be the problem ?
You have a bug in your searchStack() implementation. You are losing elements if you find the one you are looking for and it isn't the topmost one.
How to fix your searchStack() method:
keep popping z until you have an empty ArrayStack. While doing so, add the value to a queue.
create valIndex and assign it -1.
Then go through the queue and remove the items from it and adding them to z. While doing so, check for the last occurence of the desired value and save it in valIndex.
if valIndex equals -1 return it. Else, use following equation to convert it to correct index and return:
valIndex = (z.size - 1) - valIndex

Implement a Set class using an array

My Java assignment is to implement a set class by using an array.
The assignment won't allow me import the set class from the library, so I have to make it on my own. When I tried to print out the array, it prints out numbers in repeats, not unique numbers. I don't know where the problem is, so if you guys can find any errors in my code, it would be great. I tried to add numbers 2, 3, and 4 to the set, so the result should be 2 3 4, but the code shows me 2 3 2 3 2.
I think the source of the problem is from the add method from the set class, but I don't know what the problem is exactly.
import java.util.Arrays;
public final class Set implements SetInterface
{
private int[] set;
private int size;
private int capacity;
public Set(int c)
{
capacity = c;
set = new int[capacity];
size = 0;
}
public boolean contains(int x)
{
boolean contains = false;
for(int i = 0; i<capacity; i++)
{
if(x == set[i])
contains = true;
else
contains = false;
}
return contains;
}
public void add(int x)
{
for(int i = 0; i<capacity; i++)
{
if(!contains(x))
{
if(size == capacity)
{
set = Arrays.copyOf(set,size*2);
}
if(set[i]==0)
{
set[i++] = x;
}
}
}
size++;
}
public boolean remove(int x)
{
boolean remove = false;
for(int i = 0; i < capacity; i++)
{
if(x == set[i])
{
set[i] = set[size -1];
size--;
remove = true;
}
if(isEmpty())
{
remove = false;
}
}
return remove;
}
public void clear()
{
set = null;
size = 0;
}
public int size()
{
return size;
}
public boolean isEmpty()
{
if(size == 0)
return true;
else
return false;
}
public int[] toArray()
{
return Arrays.copyOf(set, capacity);
}
}
This is the driver class that I test my class.
import java.util.Arrays;
public class SetDriver
{
public static void main(String[] args)
{
SetDriver driver = new SetDriver();
Set s1 = new Set(5);
s1.add(2);
s1.add(3);
s1.add(4);
driver.print(s1);
System.out.println("Size: "+s1.size());
}
public static void print(Set s)
{
for(int i = 0; i<s.toArray().length; i++)
{
System.out.print(s.toArray()[i]+" ");
}
System.out.println("");
}
}
The outputs are here:
2 3 2 3 2
Size: 3
There's a likely problem with your contains method. Suppose that you did find a duplicate. What happens is that you assign your variable to true and you continue to iterate. This stomps over the logic entirely; you could have a duplicate but never act on it because your boolean code precludes you from doing so.
Ideally, when you find a match, you must stop iterating and return immediately.
public boolean contains(int value) {
for(int setItem : set) {
if(setItem == value) {
return true;
}
}
return false;
}
You should change add method like this.
public void add(int x) {
if (contains(x))
return;
if (size >= capacity) {
capacity *= 2;
set = Arrays.copyOf(set, capacity);
}
set[size++] = x;
}

"invalid method declaration; return type required" when trying to call a method

I'm new to Java and I'm having some problems shuffling a list.
I have to write the Iterable class so that when you iterate over the queue it returns the items in a randomly order. That's why I wrote that shuffle method and then I'm calling it inside RandomizedQueueIterator class
import java.util.Iterator;
import java.util.NoSuchElementException;
public class RandomizedQueue<Item> implements Iterable<Item>
{
// instance variables
private Item[] queue;
private int N = 0;
private int R = 0;
// constructor
public RandomizedQueue()
{
queue = (Item[]) new Object[1];
}
// helper functions
private void resize(int capacity)
{
Item[] copy = (Item[]) new Object[capacity];
for (int i = 0; i < N; i++)
copy[i] = queue[i];
queue = copy;
}
private void shrink(int capacity)
{
Item[] copy = (Item[]) new Object[capacity];
int M = 0;
for (int i = 0; i < N; i++)
{
if (queue[i] != null)
copy[M++] = queue[i];
}
queue = copy;
}
// shuffle queue
private void shuffle(Item[] a )
{
int N = a.length;
for (int i = 0; i < N; i++)
{
int r = StdRandom.uniform(i + 1);
Item temp = a[r];
a[r] = a[i];
a[i] = temp;
}
}
// return wether queue is empty
public boolean isEmpty() { return queue.length == 0; }
// return size of queue
public int size() { return queue.length; }
// add item to the queue
public void enqueue(Item item)
{
if (N == queue.length) { resize(N*2); }
queue[N++] = item;
}
// remove and return a random item from the queue
public Item deque()
{
// generate a random index and store item
int random_index;
do {
random_index = StdRandom.uniform(0, N);
} while (queue[random_index] == null);
Item item = queue[random_index];
// delete item from array and increment counter of null items
queue[random_index] = null;
R += 1;
// shrink array if corresponds
if (R == (3/4 * N)) { shrink(N/2); }
// return item
return item;
}
// return a random item from the queue
public Item sample()
{
// generate a random index and store item
int random_index;
do {
random_index = StdRandom.uniform(0, N);
} while (queue[random_index] == null);
Item item = queue[random_index];
// return item
return item;
}
// iteration
public Iterator<Item> iterator()
{
return new RandomizedQueueIterator();
}
private class RandomizedQueueIterator implements Iterator<Item>
{
private int i = 0;
shuffle(queue);
public boolean hasNext()
{
return i < N;
}
public Item next()
{
if (i >= N)
{
throw java.util.NoSuchElementException;
}
return queue[i++];
}
public void remove()
{
throw new UnsupportedOperationException("Invalid operation for array");
}
}
// main method
public static void main(String[] args)
{
RandomizedQueue example = new RandomizedQueue();
example.enqueue(0);
example.enqueue(1);
example.enqueue(2);
example.enqueue(3);
example.enqueue(3);
example.enqueue(3);
example.enqueue(3);
}
}
The output when trying to compile:
2 errors found:
[line: 114] Error: invalid method declaration; return type required
[line: 114] Error: expected
line:114 > shuffle(queue);
Any help would be really appreciated.
Thanks
If you want to run the class you need to put the method call in a main method
public static void main(String...args) {
shuffle(list_test);
}
If you do this you will either define list_test as a static variable or define it inside the main method.
There are a couple of problems. One of the problems is that you are calling the function method "inside" your class not in a function. You should be calling the function outside after you have create the test object.
So In your main. Call:
list_test = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
test testObj = new test();
newList = test.shuffle(list_test); // in the case it returns a new list
where
private void shuffle(int[] a )
// and returns a new list
return shuffled_list
If you only care about shuffling items in your list, use the JDK built-in shuffle() method instead.
There are quite a few things that can be improved. Your class might look like this:
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Random;
// it is standard to use E or T for collections
public class RandomizedQueue<E> implements Iterable<E> {
// most java collections have a default size of 16, set at 2 for testing
private static final int DEFAULT_INITIAL_CAPACITY = 2;
private static final Random GENERATOR = new Random();
// have good variable names
private boolean iterating = false; // to avoid concurrent modification
private E[] queue;
private int size = 0;
#SuppressWarnings("unchecked")
public RandomizedQueue() {
queue = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
// remove and return a random item from the queue
public E dequeue() {
if (iterating) {
throw new ConcurrentModificationException();
}
return dequeue(GENERATOR.nextInt(size));
}
// add item to queue
public void enqueue(E item) {
if (iterating) {
throw new ConcurrentModificationException();
}
if (size == queue.length) {
resize(size * 2);
}
queue[size++] = item;
}
// return whether queue is empty
public boolean isEmpty() {
return size == 0;
}
// iteration
public Iterator<E> iterator() {
return new RandomizedQueueIterator();
}
// return a random item from the queue
public E sample() {
if (isEmpty()) {
throw new NoSuchElementException("trying to sample from empty queue");
}
return queue[GENERATOR.nextInt(size)];
}
// shuffle queue
public void shuffle() {
for (int i = size - 1; i >= 0; i--) {
swap(i, GENERATOR.nextInt(i + 1));
}
}
// return size of queue
public int size() {
return size;
}
// helper functions
private E dequeue(int randomIndex) {
if (isEmpty()) {
throw new NoSuchElementException("trying to remove from empty queue");
}
size--;
// resize if only 1/4 of the queue is full
if (size < queue.length / 4) {
resize(queue.length / 2);
}
// since all get data methods are random, only need to swap on remove
swap(randomIndex, size);
E randomItem = queue[size];
queue[size] = null;
return randomItem;
}
private void resize(int capacity) {
// copyOf is substantially faster since it uses arraycopy which is in native code
queue = Arrays.copyOf(queue, capacity);
}
// swap data at indices i and j
private void swap(int i, int j) {
E temp = queue[j];
queue[j] = queue[i];
queue[i] = temp;
}
private class RandomizedQueueIterator implements Iterator<E> {
private int currentIndex = 0;
private int indexToRemove = -1;
private RandomizedQueueIterator() {
iterating = true;
shuffle();
}
public boolean hasNext() {
return currentIndex < size;
}
public E next() {
if (currentIndex >= size) {
throw new NoSuchElementException();
}
indexToRemove = currentIndex;
E nextElement = queue[currentIndex++];
if (currentIndex == size) {
iterating = false;
}
return nextElement;
}
public void remove() {
if (indexToRemove == -1) {
throw new IllegalStateException();
}
// print for testing
System.out.println("r: " + dequeue(indexToRemove));
currentIndex--;
indexToRemove = -1;
}
}
// main method
public static void main(String[] args) {
int exampleSize = 7;
System.out.println("example 1:");
RandomizedQueue<Integer> example1 = new RandomizedQueue<>();
for (int i = 0; i < exampleSize; i++) {
example1.enqueue(i);
}
System.out.println("size: " + example1.size());
for (int i = 0; i < exampleSize; i++) {
System.out.println("d: " + example1.dequeue());
}
System.out.println("size: " + example1.size());
System.out.println("\nexample 2:");
RandomizedQueue<Integer> example2 = new RandomizedQueue<>();
for (int i = 0; i < exampleSize; i++) {
example2.enqueue(i);
}
System.out.println("size: " + example2.size());
Iterator<Integer> iterator = example2.iterator();
// iterator.remove(); throws IllegalStateException
while (iterator.hasNext()) {
System.out.println("i: " + iterator.next());
iterator.remove();
System.out.println("size: " + example2.size());
// iterator.remove(); should throws IllegalStateException
}
}
}
Use this to give you ideas on how to write your class.

Categories