tags:

views:

97

answers:

2

I'm learning queues from a book. I've got into a problem while learning circular queue. The author from which I'm learning uses the following piece of code to explain how an element is inserted in a circular queue.

#define MAX 100
char *p[MAX];
int spos = 0; // spos: holds the index of the **next free** storage location

int rpos = 0;// rpos: holds the index of the next item to retrieve

void qstore(char *q)
{
  /* The queue is full if either spos is one less than rpos
      or if spos is at the end of the queue array and rpos
      is at the beginning.
  */
  if(spos+1= =rpos || (spos+1==MAX && !rpos)) <-- /***Problem is here**. Is it even  
                                                    correct?*/
  {
     printf(''List Full\n");
     return;
  }
  p[spos] = q;
  spos++;

  if(spos==MAX) 
  spos = 0; /* loop back */
}

He further states that: The queue is full when the store index is one less than the retrieve index; otherwise, there is room in the queue for another event.

SO, acc. to the author, if spos (which holds the index of the next free storage location) is equal to 4 and rpos=5, then the queue is full. Isn't this incorrect? Because spos=3 means that the memory location at p[3] is empty.


So I decided to change the program.

#define MAX 100
char *p[MAX];
int spos = 0; // spos: holds the index of the **last allocated** storage location

int rpos = 0;// rpos: holds the index of the next item to retrieve

void qstore(char *q)
{
  /* The condition for queue full is same as the previous program*/

 /* The queue is full if either spos is one less than rpos
      or if spos is at the end of the queue array and rpos 
      is at the beginning.
  */

if((spos+1==rpos) || (spos+1==MAX && rpos==0)) // Also changed syntax of test condition.
 {
   printf("Queue Full\n");
 } 

spos++

if((spos+1==MAX) && (rpos!=0))
 {
   spos=0;
 }
else
{
  spos++;
}

 p[spos]=q;

}

Is my code correct?

+4  A: 

The author's implementation is not wrong and is intentional, but you won't see it unless you think about/see the dequeue process. The problem is how do you determine if the queue when empty?

The queue is empty when spos == rpos. If you don't say the queue is full when spos+1 == rpos, but spos == rpos you have lost the ability to tell the difference between a full and empty queue.

You are correct however is noticing that you will leave one queue entry free. You queue will only hold 99 items and not 100. That "missing" is the price you pay for needing to distinguish between a full and empty circular queue without using any additional variables besides rpos, spos, and queue.

shf301
+1 exactly right
Bill Forster
Thanks!So my code is wrong?
Naruto Uzumaki
Yes your code is wrong. It increments spos twice so you'll only be using every other entry in p.
shf301
Oh! That's an unintentional mistake. I edited this code. There wasn't an else check before and when I added it later, I must've forgotten deleting the previous statement. If I delete that extra increment before the if-else block, will my code be correct?I guess not, I need to account for nulls perhaps, and I might have problem in finding a check for empty queue.
Naruto Uzumaki
A: 

Also, what does this part evaluate to? (spos+1==MAX && !rpos)

What exactly is "!rpos"?

Naruto Uzumaki
I think I get it now. It's a logical Not operations. Converts the operand to bool and evaluates its value. Basically, here it means that 'rpos==0'. Is it correct?http://msdn.microsoft.com/en-us/library/1k6w8551%28VS.80%29.aspx
Naruto Uzumaki
Yes !rpos is equivalent to rpos == 0 in C. !rpos is now considered bad form (IMHO) since what you want to check for is that rpos is zero, not rpos is false. But there is a long history of doing things like !rpos is C.
shf301
Thank you.This was very helpful.
Naruto Uzumaki