Stack and Queue
Stack and Queue
By Ankush Saklecha
What are the different abstract data types? Explain.
Abstract Data Types (ADTs) define a set of operations on data without specifying the
internal implementation. They provide a logical description of how data should be used
and manipulated rather than how it is stored in memory.
1. List ADT
The List ADT (Abstract Data Type) is a sequential collection of elements that supports a
set of operations without specifying the internal implementation. It provides an ordered
way to store, access, and modify data.
The List ADT need to store the required data in the sequence and should have the following operations:
get(): Return an element from the list at any given position.
insert(): Insert an element at any position in the list.
remove(): Remove the first occurrence of any element from a non-empty list.
removeAt(): Remove the element at a specified location from a non-empty list.
replace(): Replace an element at any position with another element.
size(): Return the number of elements in the list.
isEmpty(): Return true if the list is empty; otherwise, return false.
isFull(): Return true if the list is full; otherwise, return false.
2. Stack ADT
In Stack ADT, the order of insertion and deletion should be according to the FILO or LIFO Principle.
Elements are inserted and removed from the same end, called the top of the stack. It should also
support the following operations:
push(): Insert an element at one end of the stack called the top.
pop(): Remove and return the element at the top of the stack, if it is not empty.
peek(): Return the element at the top of the stack without removing it, if the stack is not empty.
size(): Return the number of elements in the stack.
isEmpty(): Return true if the stack is empty; otherwise, return false.
isFull(): Return true if the stack is full; otherwise, return false.
3. Queue ADT
The Queue ADT follows a design similar to the Stack ADT, but the order of insertion and
deletion changes to FIFO. Elements are inserted at one end (called the rear) and removed
from the other end (called the front). It should support the following operations:
enqueue(): Insert an element at the end of the queue.
dequeue(): Remove and return the first element of the queue, if the queue is not
empty.
peek(): Return the element of the queue without removing it, if the queue is not
empty.
size(): Return the number of elements in the queue.
isEmpty(): Return true if the queue is empty; otherwise, return false.
Q. What is Stack? Explain the operations performed on stack with a program.
• Algo_PUSH(stack[maxsize],item)
{
1. If top = maxsize-1 then “stack full”;
2. else
3. {
4. Set top =top+1;
5. Stack[top] = item;
6. }
}
Complexity = ?
• Static implementation:
• Algo_POP(stack[maxsize])
{
1. If top = -1 then “stack empty”;
2. else
3. {
4. Set top =top-1;
5. }
}
Complexity = ?
Dynamic implementation:
struct node
{
int info ;
struct node *nxt;
}*top = null;
top
typedef struct node N;
top = (N *)malloc(sizeof(N);
top
topinfo = 10;
topnxt =null; 10 X
•Algo_PUSH(*top,item)
{
1. P = (N *) malloc(sizeof(N);
2. If(P==null) then “stack full”;
3. else
4. {
5. Pinfo = item;
6. Pnxt = top;
7. top = p;
8. }
}
•Algo_POP(*top)
{
1. If(top==null) then “stack empty”;
2. else
3. {
4. P = top;
5. top = topnxt;
6. free(p);
7. }
}
• Applications of stack
• Infix expression to Prefix expression
• Infix expression to Postfix expression
• Prefix expression evaluation
• Postfix expression evaluation
• To solve recursive algorithm
• Tower of hanoi problem
• Tree traversal
• Graph traversal etc.
Infix expression : a + b
• Queues are widely used as waiting lists for a single shared resource like
printer, disk, CPU.
• Queues are used in asynchronous transfer of data (where data is not being
transferred at the same rate between two processes) for eg. pipes, file IO,
sockets.
• Queues are used as buffers in most of the applications like MP3 media
player, CD player, etc.
• Queue are used to maintain the play list in media players in order to add and
remove the songs from the play-list.
• Queues are used in operating systems for handling interrupts.
Example
R= -1 and F = -1 R= 0 and F = 0
20
0 1 2 3 4 5 0 1 2 3 4 5
FR
(a) Empty Queue FR (b) Queue with one element
R= 1 and F = 0 R= 2 and F = 0
20 30 20 30 40
0 1 2 3 4 5 0 1 2 3 4 5
F R F R
(c) Queue with two element (d) Queue with three element
Example
R= 2 and F = 0 R= 2 and F = 1
20 30 40 30 40
0 1 2 3 4 5 0 1 2 3 4 5
F R F R
(a) Queue with three element (b) Queue with two element
R= 2 and F = 2
40
0 1 2 3 4 5
FR
(c) Queue with one element
Static Implementation:
Algo_Enqueue(Q[maxsize], item)
{
1. if (rear == maxsize-1 )then “queue full”
2. else
3. {
4. if( rear == front) then
(a) rear = rear +1;
(b) front = front +1;
(c) Q[rear] = item;
5. else
(a) rear = rear + 1;
(b) Q[rear] = item;
6. }
7. }
Complexity?
Static Implementation:
Algo_Dequeue(Q[maxsize])
{
1. if (front == -1 )then “queue empty”
2. else
3. {
4. if( rear == front) then
(a) rear = -1;
(b) front = -1;
5. else
(a) front = front + 1;
6. }
7. }
Complexity?
Dynamic implementation:
struct node
{
int info ;
struct node *nxt;
}*front,*rear ;
front rear
typedef struct node N;
p = (N *)malloc(sizeof(N); p
rear=front=p;
else
(a) Pinfo = item;
(b) Pnxt = null; Complexity?
(c) rearnxt = P;
(d) rear =P;
}
Dequeue(front)
{
If (front = =null) then underflow;
else
{
if (front == rear)
{
(a) p = front;
(b) front = rear = null;
(c) free(p);
}
else
{
(a) p=front;
(b) front = frontnxt; Complexity?
(c) free(p);
}
Problem with Linear Queue
Circular Queue
• One of the solution of this problem is circular queue. In the circular queue, the first index
comes right after the last index. You can think of a circular queue as shown in the following
figure.
30 5
Rear
20 10
Rear
Rear
Circular Queue:
6
1
2
5
4 3
Equeue :
rear =(rear+1)%maxsize;
Dequeue:
front = (front+1) % maxsize
CQueue full:
front = (rear+1)%maxsize;
Cqueue Empty:
front =rear = -1
Static Implementation:
Algo_Enqueue(CQ[maxsize], item)
{
1. if (front == (rear+1) % maxsize )then “queue full”
2. else
3. {
4. if( rear == front) then
(a) rear = 0;
(b) front = 0;
(c) CQ[rear] = item;
5. else
(a) rear = (rear + 1)%maxsize;
(b) CQ[rear] = item;
6. }
7. }
Complexity?
Static Implementation:
Algo_Dequeue(CQ[maxsize])
{
1. if (front == -1 )then “queue empty”
2. else
3. {
4. if( rear == front) then
(a) rear = -1;
(b) front = -1;
5. else
(a) front = (front + 1)%maxsize;
6. }
7. }
Complexity?
1. Creation :
struct node
{
int info ;
struct node *nxt;
}*front,*rear ;
front rear
typedef struct node N;
rear = (N *)malloc(sizeof(N);
front = rear;
rear
front
rearinfo = 10;
rearnxt =rear; 10
front=rear; rear
front
10 20
rearnxt = (N *)malloc(sizeof(N);
rearnxtinfo = 20;
rearnxtnxt = rear;
Enqueue(front, item)
{
P = (N *)malloc(sizeof(N);
0 1 2 3 4
EQ DQ
DQ EQ
front rear
• Operations on Deque:
Mainly the following four basic operations are performed on queue:
insertFront(): Adds an item at the front of Deque.
insertLast(): Adds an item at the rear of Deque.
deleteFront(): Deletes an item from front of Deque.
deleteLast(): Deletes an item from rear of Deque.
insertFront(): insertRear():
EQ : EQ :
Q full : Q full :
DeleteFront(): DeleteRear():
DQ : DQ :
Q empty : Q empty :
insertFront(): insertRear():
DeleteFront(): DeleteRear():
Item
priority
• A typical priority queue supports following operations.
insert(item, priority): Inserts an item with given priority.
getHighestPriority(): Returns the highest priority item.
deleteHighestPriority(): Removes the highest priority item
• insert() operation can be implemented by adding an item at end of array in O(1)
time.
• getHighestPriority() operation can be implemented by linearly searching the
highest priority item in array. This operation takes O(n) time.
• deleteHighestPriority() operation can be implemented by first linearly searching an
item, then removing the item by moving all subsequent items one position back.
Applications of Priority Queue:
1) CPU Scheduling
2) Graph algorithms like Dijkstra’s shortest path algorithm,
Prim’s Minimum Spanning Tree, etc.
3) All queue applications where priority is involved.
Thank You