7

Is it possible to implement a circular queue by use of an array, without having a counter to count the number of items in the queue or without wasting any entry of the array ?

What I guess :

It's not possible , let's assume that we have two pointers front and rear, the first one points to the first element of the queue ,

we can define the rear pointer in two ways :

1.It points to the last element which was inserted into the queue , so the next entry is the possible place for the next element which will be inserted

2.It points to the place where the next element is going to be inserted

In either case we cannot distinguish between full & empty queue if we don't waste at least one entry of the array or if we don't keep a counter counting the number of inserted - number of deleted elements

4 Answers 4

8

Your concerns are usually recognized as the full vs. empty difficulty of circular queues. Quoting:

To solve this confusion there are a number of solutions:

  1. Always keep one slot open.
  2. Use a fill count to distinguish the two cases.
  3. Use an extra mirroring bit to distinguish the two cases.
  4. Use read and write counts to get the fill count from.
  5. Use absolute indices.
  6. Record last operation.

Numbers 1, 2, and 4 you address directly in your question. They do consume certain amounts of memory aside from the array and start/end (or front/rear as you name them) indices/pointers. The other solutions also consume memory.

#3 - use a mirroring bit

Only adds one extra boolean or enum, essentially isEmpty or isFull. The idea, logic and proof of this approach is more complicated.

#5 - absoulte indices

Indices are incremented when an operation is performed and never reduced. They are essentially counters of the number of operations of each type performed. This has other drawbacks.

#6 - record last operation

Essentially the same as #3, but different semantics.

Anyways, all those links are to the wikipedia article. I highly recommend it. There may be other approaches, but it would be hard to improve on one of the 6 approaches outlined in your article. They all have drawbacks as well as advantages, so think carefully about the intended use case before settling on an implementation.

Sign up to request clarification or add additional context in comments.

Comments

3

As I once implemented it I used an additional bool called 'empty'. You are right, one can not distinguish in the case that both pointers are at the same location.

Depending on what pointers you use, you could use the lowest bit of one pointer to store the empty variable.
In case size is a variable integer you could also use a negative value to indicate that the queue has no elements.

Comments

2

at the start, let first=0, rear=-1;

we add it the following way..... array[rear]; rear=(rear+1)%MAX;

we remove it the following way.. array[front]; front=(front+1)%MAX;

while removing an element from the array, we can add a condition after it as follows...
if(front==rear+1) first=0, rear=-1

then the empty condition can be given as...

if(rear==-1) printf("Empty");

the full condition will be then...

if ( ( front==(rear+1) || (front==0 && rear==(n-1) ) && rear!=-1 ) printf("Full");

this might work. no "count" function used

3 Comments

This is an interesting approach, but you still technically lose a bit to track the empty or full: the sign bit. That's a good choice, in my opinion, because a queue that exhausts a 2 billion count on a 4-byte size is going to have other problems. +1 to you.
first is a typo? i.e first meant front ?
This technique works well if you're tracking things via pointers too (NULL rear pointer, anyone?)
0

An alternative is to use three pointers, where the third pointer points to a place in-between the two pointers. There are a number of ways this could be implemented. The key thing to note though is that the middle pointer only needs to tell the following two things.

  • The queue is empty. All pointers point to the same place (the second definition for rear pointer).
  • The queue has 1 element and removing an element will make it empty. Middle pointer and another pointer points to the same place.

This can simply be done by keeping the middle pointer in between the first and last, and offset by one from either the first or last pointer as long as the queue has 1 or more elements.

This is probably at best only a slight improvement to using a counter, and may even be worst.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.