1 2
|
for (int i = 0; i < tail - 1; i++){
data[i] = data[i + 1];
|
I'm sorry to say this, but your basic algorithm is wrong. You shouldn't move any items when you dequeue, you should just adjust
tail
.
The idea here is that top always points to the place where you will insert the next item and tail points to the next item that you will dequeue. So as a first approximation:
1 2
|
enqueue(item) { data[top++] = item; }
item dequeue() { return data[tail++]; }
|
So you add items at positions 1,2,3,4... and you remove them in the same order.
There are several things wrong with this first approximation:
- enqueue assumes that
data
has infinite space.
- dequeue assumes that the queue isn't empty.
- it wastes space. once you've enqueued and dequeued the item at position k, that memory is never used again.
To fix this, you use a
circular buffer. Suppose you have space for 100 items, when
enqueue
gets to the 100th item, you reset
top
back to zero. By that point, you hope that that first item has been dequeued so that you can reuse position zero.
Dequeue() does the same thing: when you dequeue item last item, you reset tail to zero.
Now you just have to worry about when the queue is full and when it's empty. It's full when you would try to enqueue into an existing item, and it's empty if you try to dequeue an item that doesn't exist. To code these, first make sure you have clearly defined exactly what top and tail represent. Does top point to the location where the next item goes, or does it point to the location of the most recently inserted item? Ditto with tail. Once you define what they are, you can do the checks for full and empty queue.