Creating a dequeue - java

I'm trying to create an array-based dequeue but I can't get the order of the output right.
Right now it is bounded but I will probably use unbounded once I figure out how to work the dequeue right.
Here is my code:
public class ArrayBndDequeue<T> implements BoundedDequeueInterface<T>
{
protected final int DEFCAP = 100; // default capacity
protected T[] queue; // array that holds queue elements
protected int numElements = 0; // number of elements n the queue
protected int front = 0; // index of front of queue
protected int rear; // index of rear of queue
public ArrayBndDequeue()
{
queue = (T[]) new Object[DEFCAP];
rear = DEFCAP - 1;
}
public ArrayBndDequeue(int maxSize)
{
queue = (T[]) new Object[maxSize];
rear = maxSize - 1;
}
public void enqueue(T element)
// Throws QueueOverflowException if this queue is full;
// otherwise, adds element to the front of this queue.
{
if (isFull())
throw new DequeueOverflowException("Enqueue attempted on a full queue.");
else
{
front = (front + 1) % queue.length;
queue[front] = element;
numElements = numElements + 1;
}
}
public T dequeue()
// Throws QueueUnderflowException if this queue is empty;
// otherwise, removes rear element from this queue and returns it.
{
if (isEmpty())
throw new DequeueUnderflowException("Dequeue attempted on empty queue.");
else
{
T toReturn = queue[rear];
queue[rear] = null;
rear = (rear + 1) % queue.length;
numElements = numElements - 1;
return toReturn;
}
}
public boolean isEmpty()
// Returns true if this queue is empty; otherwise, returns false
{
return (numElements == 0);
}
public boolean isFull()
// Returns true if this queue is full; otherwise, returns false.
{
return (numElements == queue.length);
}
}
And this is my main class:
public class Dequeue
{
public static void main(String[] args)
{
Scanner userInput = new Scanner(System.in);
String line;
BoundedDequeueInterface<String> queue;
queue = new ArrayBndDequeue<String>(3);
for (int i = 1; i <= 3; i++)
{
System.out.print("Enter a line of text > ");
line = userInput.nextLine();
queue.enqueue(line);
}
System.out.println("\nOrder is:\n");
while (!queue.isEmpty())
{
line = queue.dequeue();
System.out.println(line);
}
}
}
When I run the program, I usually type in:
1
2
3
And the output comes out as:
2
3
1
Any help? If you need anymore pieces of my code, just let me know!

During enqueue you are at first adding +1 to front, then set the object, but you need to do it the opposite order.
On the other hand it is a very bad idea to implement your own Queue class (unless you do it for learning of course), as Java already has a high-speed, reliable and well tested class for this. You can have a look at the source code of the Java queue class for ideas on how to do it properly.

The problem you describe stems from the following expression during insertion (equally applies to removal):
this.front = (this.front + 1) % this.queue.length;
This evalates to:
(0 + 1 % 3) = 1
(1 + 1 % 3) = 2
(2 + 1 % 3) = 0
Because as the third value is stored, due to the size of the queue being 3, you get 3 % 3 which is 0. So the value is stored at index 0.
Have a look at the definition of this algorithm in the ArrayDeque of the JDK. They do it like this:
public void addFirst(E e) {
if (e == null)
throw new NullPointerException();
elements[head = (head - 1) & (elements.length - 1)] = e;
if (head == tail)
doubleCapacity();
}

I think you meant the following (although your overall rational is correct)
Correction
(0+1) % 3 = 1
(1+1) % 3 = 2
(2+1) % 3 = 0
Instead of your example (since % operator has higher precedence order equivalent to multiplication or division from left to right):
(0 + 1 % 3) = 1 => 1
(1 + 1 % 3) = 2 => 2
(2 + 1 % 3) = 0 => 3

Related

ArrayQueue -> RandomQueue implementation: Issues excluding a random element

I'm attempting a problem from Pat Morin's Open Data Structures textbook, based on his ArrayQueue implementation:
https://opendatastructures.org/ods-java/2_3_ArrayQueue_Array_Based_.html
"Exercise 2..3 Design and implement a RandomQueue. This is an implementation of the Queue interface in which the remove() operation removes an element that is chosen uniformly at random among all the elements currently in the queue. (Think of a RandomQueue as a bag in which we can add elements or reach in and blindly remove some random element.) The add(x) and $ remove() operations in a RandomQueue should run in constant time per operation."
His code for remove():
T remove() {
if (n == 0) throw new NoSuchElementException();
T x = a[j];
j = (j + 1) % a.length;
n--;
if (a.length >= 3*n) resize();
return x;
}
Logically, what I'm trying to do is:
Swap a random element and the next element.
Return the next element (now swapped with another random element).
I must be missing something, because performing this operation returns some elements multiple times, and never returns others. My code (renamed variables for clarity):
public T remove() {
if (count == 0) throw new NoSuchElementException();
Random random = new Random();
int randIndex = random.nextInt(count);
T objTemp = array[nextElem];
array[nextElem] = array[randIndex];
array[randIndex] = objTemp;
T obj = array[nextElem];
// Increment next element:
nextElem = (nextElem + 1) % array.length;
// Decrement element count:
count--;
if (array.length >= (3 * count))
resize();
return obj;
}
What am I doing wrong, here? Why am I getting some elements multiple times, and others not at all?
(Note: This is for an online university course.)
Credit to Andreas for pointing out my silly mistake.
I needed to get my index based on the index of the head (of course!). This code works:
public T remove() {
if (count == 0) throw new NoSuchElementException();
Random random = new Random();
int randIndex = random.nextInt(count);
int safeRandomIndex = (headIndex + randIndex) % array.length;
// Swap that randomly chosen element with our nextElem:
T objTemp = array[headIndex];
array[headIndex] = array[safeRandomIndex];
array[safeRandomIndex] = objTemp;
T obj = array[headIndex];
headIndex = (headIndex + 1) % array.length;
count--;
if (array.length >= (3 * count))
resize();
return obj;
}

Dequeue method not correctly deleting elements within queue

My dequeue method currently does not delete the item I wish for it too, instead it deletes the last element from the collection. For example,
If I add in the elements: 1, 2, 3
My toString method will return 1, 2, 3 as expected.
Then when I use my driver to call dequeue, it should dequeue the 0th element, 1 in this case.
Although, the method says "Removed element 1 from the queue" prompting that the T result variable has embodied the correct value, although the method does not work as expected, as when calling the toString method after to print the contents, it will print: 1, 2
Then when I call the enqueue method again, on the same queue, if I enqueue the String 3, it will print this as the new queue: 3, 2, 3
I am confused as to where my logic error is, as I assume it is with the extreme case of the collection being filled, but I still run into errors with my dequeue method when the collection is not at max. I attached my code below.
public class QueueRA<T> implements QueueInterface<T> {
protected T[] items;
protected int front, back, numItems;
#SuppressWarnings("unchecked")
public QueueRA() {
front = 0;
numItems = 0;
back = 0;
items = (T[]) new Object[3];
}
#Override
public boolean isEmpty() {
return numItems == 0;
}
#Override
public void enqueue(T newItem) throws QueueException {
if(numItems == items.length) {
resize();
enqueue(newItem);
}
else {
items[back] = newItem;
back = (back + 1) % items.length;
numItems++;
}
}
#Override
public T dequeue() throws QueueException {
T result;
if(numItems != 0) {
result = items[front];
items[front] = null;
front = (front + 1) % items.length;
numItems--;
}
else {
throw new QueueException("The queue does not contain any elements.");
}
return result;
}
#SuppressWarnings("unchecked")
#Override
public void dequeueAll() {
back = 0;
front = 0;
numItems = 0;
items = (T[]) new Object[3];
}
#Override
public T peek() throws QueueException {
T result;
if(numItems != 0) {
result = items[front];
}
else {
throw new QueueException("The queue does not contain any elements.");
}
return result;
}
/**
*
*/
#SuppressWarnings("unchecked")
protected void resize() {
T[] newItems = (T[]) new Object[numItems+4];
for(int i = 0; i < numItems; i++) {
newItems[i] = items[i];
}
this.front = 0;
this.back = numItems;
this.items = newItems;
}
/**
*
*/
public String toString() {
String toReturn = "";
for(int i = 0; i < numItems; i++) {
if( (i+1) == numItems) {
toReturn = toReturn.concat(items[i] + " ");
}
else {
toReturn = toReturn.concat(items[i] + ", ");
}
}
return toReturn;
}
}
Your toString() and resize() methods are wrong.
In your example code, you created an arraySize of 3 initially and then added 1, 2, and 3. This occupies all the 3 slots in the array and your numItems is set to 3. The front is set to 0 and back is also set to 0 because after adding 3, your algorithm is:
back = (back+1)%items.length;
back was initially 2. Now it is calculated as:
-> (2+1)%3
-> 3%3
-> 0
So your back is 0 at this moment.
Now, when you call dequeue(), the front pops 1 out. So now your array looks like this:
items[0] -> empty
items[1] -> 2
items[2] -> 3
back = 0
front = 1
So, when you enque next and add 3, your enqueue() method checks that number of items in the system is less than size of the array (2 < 3) and adds 3 to the location pointed by back (which is 0 now) and increments it to 1. So, your array looks like this now:
items[0] -> 3
items[1] -> 2
items[2] -> 3
back = 1
front = 1
Now, in your toString() method, without considering the values of front and back, you start from 0 to end:
for(int i = 0; i < numItems; i++) {
.
.
.
}
What you need to be doing is start at i = front. if front < back, that means that you travel lineraly from "front" to "back" and print everything. If front > back then you do two loops:
for(int i=front; i < arr.length; i++) {
// Code to print arr[i]
}
for(int i=0; i < back; i++) {
// Code to print arr[i]
}
This way, it will print from front to end and then from 0 to back.
Also, your resize method is wrong for the same reason. You cannot copy from 0 to numItems, you need to start the copy at "front" and then progress like how I wrote for the toString(). Doing this will ensure that your queue's order is preserved across multiple resizes.
Adding to #Arun Subramanian's answer.
Your resize() method was simply copying all of the elements sequentially from items to newItems, then setting front = 0 and back = numItems. Which would have been fine if you had implemented the queue sequentially. However, your implementation of a queue is not sequential, it's a circular / ring implementation. Therefor you have to copy the elements in a circular way.
One way to do this is mentioned in #ArunSubramanian's answer, "If front < back, that means that you travel linearly from front to back and print everything. If front > back then you do two loops." Another way is to use a do-while loop with modular arithmetic, as in the following:
#SuppressWarnings("unchecked")
protected void resize() {
T[] newItems = (T[]) new Object[numItems + 4];
int i = 0; // index used to copy items to newItems
// do-while used in case the queue is full (i.e. front == back)
do {
newItems[i] = items[front];
// modular arithmetic used to circle back on items
front = (front + 1) % items.length;
i += 1;
} while(front != back);
this.front = 0;
this.back = numItems;
this.items = newItems;
}
Similarly your toString() method can be implemented in the following way:
#Override
public String toString() {
String toReturn = "";
// need this check, otherwise do-while will illegally access items[0]
if(!isEmpty()) {
int len = items.length;
int i = front;
// do-while used in case front == back
do {
String delim = ((i+1) % len == back) ? " " : ", ";
toReturn += items[i] + delim;
i = (i+1) % len; // modular arithmetic used to circle back
} while(i != back);
}
return toReturn;
}

Java: Recursive reheapUp (bubbleUp) method for Heap data structure

I've been trying to write a recursive method that reshapes a heap data structure when an element is enqueued, but I cannot get it to work correctly.
I was able to get a perfectly working recursive reheapDown method, so I have no idea why this one won't work. Here is the class I've been working on, which includes the iterative version of reheapUp which I'm using as a template for designing the recursive version:
public class Heap<T extends Comparable<T>> implements PriQueueInterface<T>
{
private ArrayList<T> elements; // priority queue elements
private int lastIndex; // index of last element in priority queue
private int maxIndex; // index of last position in ArrayList
public Heap(int maxSize)
{
elements = new ArrayList<T>(maxSize);
lastIndex = -1;
maxIndex = maxSize - 1;
}
public boolean isEmpty()
// Returns true if this priority queue is empty; otherwise, returns false.
{
return (lastIndex == -1);
}
public boolean isFull()
// Returns true if this priority queue is full; otherwise, returns false.
{
return (lastIndex == maxIndex);
}
private void reheapUp(T element)
// Current lastIndex position is empty.
// Inserts element into the tree and ensures shape and order properties.
{
int hole = lastIndex;
while ((hole > 0) // hole is not root and element > hole's parent
&&
(element.compareTo(elements.get((hole - 1) / 2)) > 0))
{
// move hole's parent down and then move hole up
elements.set(hole,elements.get((hole - 1) / 2));
hole = (hole - 1) / 2;
}
elements.set(hole, element); // place element into final hole
}
private void recReheapUp(T element)
{
int hole = lastIndex;
//hole is not root and element > hole's parent
if (hole > 0)
{
if (element.compareTo(elements.get((hole - 1) / 2)) > 0)
{
elements.set(hole,elements.get((hole - 1) / 2));
hole = (hole - 1) / 2;
}
}
//base condition
if (hole == 0 && element.compareTo(elements.get((hole - 1) / 2)) <= 0))
{
elements.set(hole, element); // place element into final hole
return;
}
recReheapUp(element);
}
public void enqueue(T element) throws PriQOverflowException
// Throws PriQOverflowException if this priority queue is full;
// otherwise, adds element to this priority queue.
{
if (lastIndex == maxIndex)
throw new PriQOverflowException("Priority queue is full");
else
{
lastIndex++;
elements.add(lastIndex,element);
recReheapUp(element);
}
}
The reheapUp() and recReheapUp() methods are called whenever an item is enqueued into the heap. I've reworked the recReheapUp() method so many times it's not even worth posting all the changes I've attempted.
I will say that I think the issue lies in my base case, although there may be logical flaws in the general case as well.
I keep getting stack overflow errors no matter what I do, which tells me the recursive method isn't terminating properly. I just recently switched to nested if statements for my recursive method, but I'm not sure if that helped or hurt my cause.
Looks like you're getting stuck in unbounded recursive calls not because there's anything wrong with your base case (although I'm not sure I understand what the inner comparison is for), but because you're effectively calling Heapify on the same element. Your recursive algorithm should know the index of the current element that may need to sift. Something like this:
private void insert(ArrayList<T> heap, T element) {
head.add(element);
heapify(heap, heap.size() - 1);
}
private void heapify(ArrayList<T> heap, int location) {
int parent = (location - 1) / 2; // -1 for zero-indexed language
// same-element comparison is OK. This will always happen at the root.
if (heap.get(parent).compareTo(heap.get(location)) > 0) {
swap(heap, location, parent);
heapify(heap, parent);
}
}
private void swap(ArrayList<T> heap, int a, int b) {
T temp = heap.get(a);
heap.set(a, heap.get(b));
heap.set(b, temp);
}
CLRS has a really excellent discussion on Heaps on pages 151-159.

FIFO Queue with random deletion

Implement a data type that supports insert an item, delete the item added least recently, and delete a random item. Each operation should take constant expected amortized time per operation and should use space (at most) proportional to the number of items in the data structure.
eg. 1 2 3 4 5 6 -> 1 2 4 5 6
I have already implemented the queue as below, but now I do not know how the delete a random item with amortized time, should I rearrange the array every time when there is a random remove like moving number after the random removed number one slot forward in array? is it a really bad practice? or should I implement the Queue using linked list? but my gut feeling tells me linked list also need average O(n) to reach the random node from the head of the linked list.
public class RandomQueue<Item> implements Iterable<Item> {
Item[] items;
int N;
int first;
int last;
public RandomQueue() {
items = (Item[]) new Object[2];
N = 0;
first = last = 0;
}
public static void main(String[] args) {
RandomQueue<Integer> rd = new RandomQueue<>();
}
public boolean isEmpty() {
return N == 0;
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < N; i++) {
sb.append(items[(first + i) % items.length]).append(" ");
}
return sb.toString();
}
private void resize(int length) {
Item[] temp = (Item[]) new Object[length];
for (int i = 0; i < N; i++) {
temp[i] = items[(first + i) % items.length];
}
items = temp;
first = 0;
last = N;
}
public void enqueue(Item item) {
if (N == items.length)
resize(items.length * 2);
items[last++] = item;
if (last == items.length)
last = 0;
N++;
}
public Item dequeue() {
if (isEmpty())
throw new NoSuchElementException("Queue is empty");
Item first = items[first];
items[first] = null;
N--;
if (first == items.length)
first = 0;
else
first++;
if (N > 0 && N == items.length / 4)
resize(items.length / 2);
return first;
}
}
The key to this problem is that you are not removing a random item from the queue you are creating a queue that excludes a random item. You should have a function in your program that accepts a queue as input and does the following:
Create a second queue that will exclude the random deleted item.
Generate a random number less than or equal to the total length of the first queue.
Create a loop that will remove items from the first queue and add them to the second queue.
If the counter in your loop equals the random number, do not add it to the second queue.
Delete the first queue and return the second queue.

Removing a element from an array list without using libraries. Java

I have implemented a function which removes an element from an array list. I should not the ArrayList libraries! See my code below:
/**
* removes a LendItem at a specified (index) position.
* This functions returns the item removed from the list or null if no such item exists. This
* function leaves no gaps, that means all items after the removed item are shifted one position.
* #param list is the item to be removed
* #param n is the index of the item to be removed
* #return the removed item
*/
public static LendItem remove(LendItemArrayList list, int n) {
if (list.next == 0) {
return null;
}
if (n < 0 || n > list.INITIAL_SIZE) {
return null;
}
LendItem itemToBeRemoved = list.lendItems[n]; // itemToBeRemoved is the item which has the index n, which we want to remove from the list.
int i;
for (i = n; i < list.next - 1; i++) { // iterate through the list, starting where the index of the itemToBeRemoved is.
list.lendItems[i] = list.lendItems[i + 1];
}
list.lendItems[i] = null;
list.next--;
return itemToBeRemoved;
}
and here is the class :
public class LendItemArrayList {
int INITIAL_SIZE = 20;
boolean resizeable = false;
LendItem[] lendItems = new LendItem[INITIAL_SIZE];
int next = 0;
}
I have tested my functions with a few test methods which have been provided, and i am only failing one of them. Specifically the test is called:
removeNonExistingElement
and it fails like this:
java.lang.AssertionError: 10 elements have been added, next should be 10 (no changes) but found 9.
EDIT:
Added the add() function.
public static boolean add(LendItemArrayList list, LendItem p) {
if (list.next == list.lendItems.length) {
if (list.resizeable == false) {
return false;
}
}
if (list.next == list.lendItems.length) {
if (list.resizeable == true) {
LendItem[] resizedList = new LendItem[list.lendItems.length*2];
for (int i = 0; i < list.next; i++) {
resizedList[i] = list.lendItems[i];
}
list.lendItems = resizedList;
}
}
list.lendItems[list.next++] = p;
return true;
}
Leave this as it is, as it checks if the indices are out of range.
if (n < 0 || n >= list.INITIAL_SIZE) {
return null;
}
Next, add this line of code:
if (list.lendItems[n] == null) {
return null;
}
Afterwards, you may or may not add the if statement which checks if the given list is empty. It makes no difference unless it is required to be used.
if (list.next == 0){
return null;
}
Change this line:
if (n < 0 || n > list.INITIAL_SIZE) {
To this:
if (n < 0 || n >= list.INITIAL_SIZE) {
>= means greater or equal. If n == list.INITIAL_SIZE, then that item can't be removed either, because since indices start with 0, the last value in a list has an index of size - 1. It's one of those things that hurt your brain when you start programming.

Categories