Java: for loop not dequeueing every element in a queue

Viewed 465

Currently, I have a linked queue with three elements in it.

LinkedQueue<Integer> queue = new LinkedQueue(); 
queue.enqueue(1);
queue.enqueue(2); 
queue.enqueue(3); 

At this point, queue.toString() gives me:

<Front>
1
2
3
<Rear>

I am trying to write a for loop that steps through queue, dequeues its elements and enqueues those elements into a temp queue.

LinkedQueue<Integer> temp = new LinkedQueue(); 
for (int i = 0; i < queue.size(); i++) {
   Integer int = queue.dequeue(); 
   temp.enqueue(int); 
}

queue.size() returns 3, which is the correct number of elements in queue, so the body of the loop should execute three times. However, when I put print statements in my for loop that inspect the elements of both queue and temp at each iteration, there are only two iterations.

Temp:
<Front>
1
<Rear>
Queue:
<Front>
2
3
<Rear>

Temp:
<Front>
1
2
<Rear>
Queue:
<Front>
3
<Rear>

I'm not sure why it's skipping the final iteration, which should give

Temp:
<Front>
1
2
3
<Rear>
Queue:
<Front>
<Rear>

To test, I changed the "i < queue.size()" to "i <= queue.size()," which not work. I also tried to put one more iteration of the body of the for loop right after the for loop itself, like so:

LinkedQueue<Integer> temp = new LinkedQueue(); 
for (int i = 0; i < queue.size(); i++) {
   Integer int = queue.dequeue(); 
   temp.enqueue(int); 
}
Integer int = queue.dequeue();
temp.enqueue(int); 

Which made it work.
TL;DR I have absolutely no idea why my for loop isn't executing the correct number of times.

2 Answers

As you are dequeuing, queue.size() is changing!

So after the first iteration, queue.size() is 2 and i is 1. After the second iteration, queue.size() is 1 and i is 2. This causes the loop to stop. Your attempt of changing < to <= didn't work because this is not an off-by-1 error, but an "off-by-2" error :)

To fix this, store the size into a variable before the loop starts:

LinkedQueue<Integer> temp = new LinkedQueue(); 
int size = queue.size();
for (int i = 0; i < size; i++) {
   Integer number = queue.dequeue(); 
   temp.enqueue(number); 
}

Or, use a while(!queue.isEmpty()) loop:

LinkedQueue<Integer> temp = new LinkedQueue(); 
while(queue.size() > 0) {
   Integer number = queue.dequeue(); 
   temp.enqueue(number); 
}

After you call queue.deque(), the size of the queue is decremented. You may store the queue size in another variable:

for (int i = 0, n = queue.size(); i < n; i++) {
   Integer value = queue.dequeue(); 
   temp.enqueue(value); 
}
Related