Module 2
Module 2
Module 2
Drawback of Queue
When item enters and deleted from the queue, the queue gradually shifts to the right as shown in
figure.
In this above situation, when we try to insert another item, which shows that the queue is full .
This means that the rear index equals to MAX_QUEUE_SIZE -1. But even if the space is available
at the front end, rear insertion cannot be done.
Overcome of Drawback using different methods
Method 1
• When an item is deleted from the queue, move the entire queue to the left so that the first element
is again at queue[0] and front is at -1. It should also recalculate rear so that it is correctly positioned.
• Shifting an array is very time-consuming when there are many elements in queue & queueFull
has worst case complexity of O(MAX_QUEUE_SIZE)
Method 2:
Circular Queue
• It is “The queue which wrap around the end of the array.” The array positions are arranged in a
circle.
• In this convention the variable front is changed. front variable points one position
counterclockwise from the location of the front element in the queue. The convention for rear is
unchanged.
CIRCULAR QUEUES
• It is “The queue which wrap around the end of the array.” The array positions are arranged in a
circle as shown in figure.
Implementation of Circular Queue Operations
• When the array is viewed as a circle, each array position has a next and a previous position. The
position next to MAX-QUEUE-SIZE -1 is 0, and the position that precedes 0 is MAX-QUEUE-
SIZE -1.
• When the queue rear is at MAX_QUEUE_SIZE-1, the next element is inserted at position 0.
• In circular queue, the variables front and rear are moved from their current position to the next
position in clockwise direction. This may be done using code
if (rear = = MAX_QUEUE_SIZE-1)
rear = 0;
else rear++;
Addition & Deletion
• To add an element, increment rear one position clockwise and insert at the new position. Here
the MAX_QUEUE_SIZE is 8 and if all 8 elements are added into queue and that can be represented
in below figure (a).
• To delete an element, increment front one position clockwise. The element A is deleted from
queue and if we perform 6 deletions from the queue of Figure (b) in this fashion, then queue
becomes empty .
• If the element I is added into the queue as in figure (c), then rear needs to increment by 1 and the
value of rear is 8. Since queue is circular, the next position should be 0 instead of 8. This can be
done by using the modulus operator, which computes remainders.
Program: Add to a circular queue
void addq(element item)
{
if(front==(rear+1)% MAX_QUEUE_SIZE)
printf(“queue is full”);
else
{
if((front==-1)&&(rear==-1))
{
front++;
rear++ ;
queue [rear] = item;
}
else{
rear = (rear +1) % MAX_QUEUE_SIZE;
queue [rear] = item;
}
}
Program: Delete from a circular queue
element deleteq()
{
if((front==-1)&&(rear==-1))
return queueEmpty( ); /* return an error key */
else
{
item=queue[front];
if(front==rear)
{
front=rear=-1;
}
else
front = (front+1)% MAX_QUEUE_SIZE;
return item;
}
Circular Queue using Dynamic Arrays
To insert an element into a circular queue using dynamic array- Assume q is pointer to an integer,
two index variables front and rear are initialized to 0 and -1 respectively. Another variable count
is initialized to 0 which indicate queue is empty. Initial size of the queue denoted by SIZE is 1.
Design: Before inserting, we check whether sufficient space is available in the circular queue. We
know that if count value is same as SIZE, then circular queue is full. The code for this condition
can be written as shown below:
if (front=(rear+1)%maxsize)
{
printf(“Q full:\n”);
return;
}
But, once the queue is full, instead of returning the control, we can increase the size of array using
realloc() function and the above code can be modified as shown below:
if (front=(rear+1)%maxsize )
{
printf(“Q Full: update size, insert item\n ”);maxsize++;
q = (int *) realloc(q, maxsize*sizeof(int) );
MULTILPLE STACKS AND QUEUES
• In multiple stacks, we examine only sequential mappings of stacks into an array. The array is one
dimensional which is memory[MEMORY_SIZE]. Assume n stacks are needed, and then divide
the available memory into n segments. The array is divided in proportion if the expected sizes of
the various stacks are known. Otherwise, divide the memory into equal segments.
• Assume that i refers to the stack number of one of the n stacks. To establish this stack, create
indices for both the bottom and top positions of this stack. boundary[i] points to the position
immediately to the left of the bottom element of stack i, top[i] points to the top element. Stack i is
empty iff boundary[i]=top[i]
➢ The left part represents the information part of the node, which may contain an entire
➢ The pointer of the last node contains a special value, called the NULL.
A pointer variable called first which contains the address of the first node. A special case is the list
that has no nodes; such a list is called the null list or empty list and is denoted by the null pointer
in the variable first.
Types of linked List:
1Singly linked list
• We have seen how a stack is created using an array. This technique of creating a stack is
easy,but the drawback is that the array must be declared to have some fixed size.
• In case the stack is a very small one or its maximum size is known in advance, then
• the array implementation of the stack gives an efficient implementation.
• But if the array size cannot be determined in advance, then the other alternative, i.e., linked
representation, is used. The linked representation of a stack is shown in Fig.3.9.1
• The push operation is used to insert an element into the stack. The new element is added at
the topmost position of the stack. Consider the linked stack shown in Fig. 3.9.2(a). To insert
an element with value 9, we first check if TOP=NULL. If this is the case, then we allocate
memory for a new node, store the value in its DATA part and NULL in its NEXT part. The
new node will then be called TOP. However, if TOP! =NULL, then we insert the new node
at the beginning of the linked stack and name this new node as TOP. Thus, the updated
stack becomes as shown in Fig. 3.9.2(b).
• The pop operation is used to delete the topmost element from a stack. However,
before deleting the value, we must first check if TOP=NULL, because if this is the case, then it
means that the stack is empty and no more deletions can be done. If an attempt is made to delete a
value from a stack that is already empty, an UNDERFLOW message is printed. Consider the stack
shown in Fig. 3.9.4 (a). In case TOP! =NULL, then we will delete the node pointed by TOP, and
make TOP point to the second element of the linked stack. Thus, the updated stack becomes as
shown in Fig. 3.9.4 (b).
Linked Queue(insertion at end ,deletion at front)
• When the array implementation of the queue gives an efficient implementation. But if the
array size cannot be determined in advance, the other alternative ,i.e.the linked
representation is used.
• In a linked queue, every element has two parts, one that stores the data and another which
holds the address of the next element. The START pointer of the linked list is used as
FRONT. Here we will also use another pointer called REAR, which will store the address
of the last element in the queue. All insertions will be done at the rear end and all the
deletions will be done at front end. If FRONT=REAR=NULL, then it indicates that the
queue is empty. The linked representation of queue is shown in Fig. 3.10.1.
• The insert operation is used to insert an element into the queue. The new element is added
as the last element of the queue. Consider the linked queue shown in Fig. 3.10.2 (a). To
insert an element with value 9, we first check if FRONT=NULL. If this is the case, then
we allocate memory for a new node, store the value in its DATA part and NULL in its
NEXT part. The new node will then be called FRONT and REAR. However, if FRONT!
=NULL, then we insert the new node at the rear end of the linked queue and name this new
node as REAR. Thus, the updated queue becomes as shown in Fig. 3.10.2(b).
Deletion:
• The delete operation is used to delete the element that is first inserted
• The delete operation is used to delete the element that is first inserted into the queue. i.e.
the element whose address is stored at FRONT.
• However, before deleting the value, we must first check if FRONT=NULL, because if this
is the case, then it means that the queue is empty and no more deletions can be done. If an
attempt is made to delete a value from a stack that is already empty, an UNDERFLOW
message is printed.
• Consider the stack shown in Fig. 3.10.4(a). To delete an element, we first check if
FRONT=NULL. If it is false, then we delete the 1st node pointed by the FRONT. The
FRONT will now point to the 2nd element of the linked queue. Thus the updated queue
becomes as shown in Fig. 3.10.4(b).
Element deleteq(int i)
{
queuePointer temp=front[i];
eement item;
if(!temp)
return queueEmpty();
item=temp->data;
front[i]=temp->link;
free(temp);
return(item);
}
Polynomial representation
Let us see how a polynomial is represented in the memory using a linked list. Consider a
polynomial 6x3 + 9x2 + 7x + 1. Every individual term in a polynomial consists of two
parts, a coefficient and a power. Here, 6, 9, 7, and 1 are the coefficients of the terms that
have 3, 2, 1, and 0 as their powers respectively. Every term of a polynomial can be
represented as a node of the linked list. Figure 3.11.1 shows the linked representation of
the terms of the above polynomial.
Polynomial Addition
Consider an example polynomial shown in Fig. 3.11.2. To add polynomial, we
examine their terms starting at the nodes pointed by a and b. There are three cases:
Program Code for polynomial addition for singly linked list
polyptr addpoly (polyptr a, polyptr b) {
{ if(a->link)
polyptr c, *temp; {
c->link=(struct c->exp=a->exp;
poly*)malloc(sizeof(struct c->coef=a->coef;
poly)); a=a->link;
c=c->link; }
c->link = NULL; if(b->link)
while( a->link && b->link) {
{ c->exp=b->exp;
if( a->exp>b->exp) c->coef=b->coef;
{ b=b->link;
c->exp=a->exp; }
c->coef=a->coef; c->link= (struct poly*)malloc
a=a->link; (sizeof(struct poly));
} c=c->link;
else if( a->exp<b->exp) c->link = NULL;
{ }
c->exp=b->exp;
c->coef=b->coef;
b=b->link;
}
else
{
c->exp=a->exp;
c->coef=a->coef + b->coef;
a=a->link;
b=b->link;
}
c->link=(struct
poly*)malloc(sizeof(struct
poly));
c=c->link;
c->link = NULL;
while (a->link || b->link)
Circular list representation of Polynomial
The zero polynomial is represented as in Fig. 3.12 (a);while a(x) = 3x 14+2x8+1 can be
represented as in Fig 3.12 (b). here link field of last node points to the 1st node in the list. So
we call this a circular linked list. To simplify the addition algorithm for polynomial
represented as circular linked list, we set coef and exp field of header node to -1. The
structure can be written as in Fig. 3.12 (c).
polyptr addpoly (polyptr a, polyptr b) {
{ if(a->link)
polyptr c, *temp; {
c->link=(struct poly*)malloc(sizeof(struct c->exp=a->exp;
poly)); c->coef=a->coef;
c=c->link; a=a->link;
temp=c; }
c->link = NULL; if(b->link)
while( a->link && b->link) {
{ c->exp=b->exp;
if( a->exp>b->exp) c->coef=b->coef;
{ b=b->link;
c->exp=a->exp; }
c->coef=a->coef; c->link= (struct poly*)malloc
a=a->link; (sizeof(struct poly));
} c=c->link;
else if( a->exp<b->exp) c->link = NULL;
{ }
c->exp=b->exp; c->link=temp;
c->coef=b->coef;
b=b->link;
}
else
{
c->exp=a->exp;
c->coef=a->coef + b->coef;
a=a->link;
b=b->link;
}
c->link=(struct poly*)malloc(sizeof(struct
poly));
c=c->link;
c->link = NULL;
while (a->link || b->link)
Program Code for polynomial addition for circular singly linked list