stack & queue
stack & queue
In-First-Out) principle and allows insertion and deletion operations from one end of
the stack data structure, that is top. Implementation of the stack can be done by
contiguous memory which is an array, and non-contiguous memory which is a linked
list. Stack plays a vital role in many applications.
The stack data structure is a linear data structure that accompanies a principle
known as LIFO (Last In First Out) or FILO (First In Last Out). Real-life examples of a
stack are a deck of cards, piles of books, piles of money, and many more.
This example allows you to perform operations from one end only, like when you
insert and remove new books from the top of the stack. It means insertion and
deletion in the stack data structure can be done only from the top of the stack. You
can access only the top of the stack at any given point in time.
Next, you will see how to represent the stacks in data structures in real-time.
You can only see the top, i.e., the top-most book, namely 40, which is kept top of the
stack.
If you want to insert a new book first, namely 50, you must update the top and then
insert a new text.
And if you want to access any other book other than the topmost book that is 40,
you first remove the topmost book from the stack, and then the top will point to the
next topmost book.
After working on the representation of stacks in data structures, you will see some
basic operations performed on the stacks in data structures.
There following are some operations that are implemented on the stack.
Push Operation
Push operation involves inserting new elements in the stack. Since you have only one
end to insert a unique element on top of the stack, it inserts the new element at the
top of the stack.
Pop Operation
Pop operation refers to removing the element from the stack again since you have
only one end to do all top of the stack. So removing an element from the top of the
stack is termed pop operation.
Peek Operation
Peek operation refers to retrieving the topmost element in the stack without
removing it from the collections of data elements.
isFull()
isFull function is used to check whether or not a stack is empty.
isEmpty()
isFull()
begin
If
return true
else
return false
else if
end
if(top == maxsize)
return true;
else
return false;
isEmpty()
begin
If
topless than 1
return true
else
return false
else if
end
Bool isEmpty()
if(top = = -1)
return true;
else
return false;
Push Operation
Step 5: Success
end if
top ->top+1;
end
top = top + 1;
stack[top] = item;
}
else {
printf(“stack is full”);
Pop Operation
Step 5: Success
return null
end if
item -> stack[top] ;
Return item;
end
If isEmpty()) {
item = stack[top];
top = top - 1;
return item;
else{
printf(“stack if empty”);
}
Peek Operation
begin to peek
return stack[top];
end
int peek()
return stack[top];
You can perform the implementation of stacks in data structures using two data
structures that are an array and a linked list.
● Array: In array implementation, the stack is formed using an array. All the
operations are performed using arrays. You will see how all operations can be
implemented on the stack in data structures using an array data structure.
● Linked-List: Every new element is inserted as a top element in the linked list
implementation of stacks in data structures. That means every newly inserted
element is pointed to the top. Whenever you want to remove an element from
the stack, remove the node indicated by the top, by moving the top to its previous
node in the list.
● Backtracking
● Function Call
● Parentheses Checking
● String Reversal
● Syntax Parsing
● Memory Management
There are three types of expression that you use in programming, they are:
● X+Y
● (X + Y ) + (A - B)
● X
● +XY
● ++XY-AB
● X
● XY+
● XY+CD-+
Similarly, the stack is used to evaluate these expressions and convert these
expressions like infix to prefix or infix to postfix.
2. Backtracking
To solve the optimization problem with backtracking, you have multiple solutions; it
does not matter if it is correct. While finding all the possible solutions in
backtracking, you store the previously calculated problems in the stack and use that
solution to resolve the following issues.
Whenever you call one function from another function in programming, the
reference of calling function stores in the stack. When the function call is terminated,
the program control moves back to the function call with the help of references
stored in the stack.
So stack plays an important role when you call a function from another function.
import java.util.Scanner;
class GetInputData
{
public static void main(String args[])
{
int num;
float fnum;
String str;
Enter a string:
Chaitanya
Input String is: Chaitanya
Enter an integer:
27
Input Integer is: 27
Enter a float number:
12.56
Input Float number is: 12.56
4. Parentheses Checking
Stack in data structures is used to check if the parentheses like ( ), { } are valid or not
in programing while matching opening and closing brackets are balanced or not.
So it stores all these parentheses in the stack and controls the flow of the program.
For e.g ((a + b) * (c + d)) is valid but {{a+b})) *(b+d}] is not valid.
5. String Reversal
Another exciting application of stack is string reversal. Each character of a string gets
stored in the stack.
The string's first character is held at the bottom of the stack, and the last character of
the string is held at the top of the stack, resulting in a reversed string after
performing the pop operation.
6. Syntax Parsing
Since many programming languages are context-free languages, the stack is used for
syntax parsing by many compilers.
7. Memory Management
● People on an escalator
● Cashier line in a store
● A car wash line
● One way exits
● Enqueue: The Enqueue operation is used to insert the element at the rear end of
the queue. It returns void.
● Dequeue: It performs the deletion from the front-end of the queue. It also
returns the element which has been removed from the front-end. It returns an
integer value.
● Peek: This is the third operation that returns the element, which is pointed by the
front pointer in the queue but does not delete it.
● Queue overflow (isfull): It shows the overflow condition when the queue is
completely full.
● Queue underflow (isempty): It shows the underflow condition when the Queue
is empty, i.e., no elements are in the Queue.
peek()
This function helps to see the data at the front of the queue. The algorithm of peek()
function is as follows −
Algorithm
return queue[front]
end procedure
Example
int peek() {
return queue[front];
isfull()
As we are using single dimension array to implement queue, we just check for the rear
pointer to reach at MAXSIZE to determine that the queue is full. In case we maintain the
queue in a circular linked-list, the algorithm will differ. Algorithm of isfull() function −
Algorithm
return true
else
return false
endif
end procedure
Example
bool isfull() {
if(rear == MAXSIZE - 1)
return true;
else
return false;
isempty():
As we are using single dimension array to implement queue, we just check for the rear
pointer to reach at MINSIZE to determine that the queue is empty. In case we maintain
the queue in a circular linked-list, the algorithm will differ.
Algorithm
return true
else
return false
endif
end procedure
If the value of front is less than MIN or 0, it tells that the queue is not yet initialized,
hence empty.
Example
bool isempty() {
return true;
else
return false;
Enqueue Operation
Queues maintain two data pointers, front and rear. Therefore, its operations are
comparatively difficult to implement than that of stacks.
The following steps should be taken to enqueue (insert) data into a queue −
Step 3 − If the queue is not full, increment rear pointer to point the next empty space.
Step 4 − Add data element to the queue location, where the rear is pointing.
procedure enqueue(data)
if queue is full
return overflow
endif
rear ← rear + 1
queue[rear] ← data
return true
end procedure
Example
if(isfull())
return 0;
rear = rear + 1;
queue[rear] = data;
return 1;
end procedure
Dequeue Operation
Accessing data from the queue is a process of two tasks − access the data where front is
pointing and remove the data after access. The following steps are taken to
perform dequeue operation −
Step 4 − Increment front pointer to point to the next available data element.
procedure dequeue
if queue is empty
return underflow
end if
data = queue[front]
front ← front + 1
return true
end procedure
Example
int dequeue() {
if(isempty())
return 0;
return data;
● Simple Queue
● Circular Queue
● Priority Queue
● Double-Ended Queue (Deque)
Simple Queue
It is the most basic queue in which the insertion of an item is done at the front of the queue
and deletion takes place at the end of the queue.
Circular Queue
A circular queue is a special case of a simple queue in which the last member is linked to the
first. As a result, a circle-like structure is formed.
Now let’s take a look at the priority queue in the data structure.
Priority Queue
In a priority queue, the nodes will have some predefined priority in the priority queue. The
node with the least priority will be the first to be removed from the queue. Insertion takes
place in the order of arrival of the nodes.
Below diagram shows how an application use priority queue for the items consumed by the
user.
In a double-ended queue, insertion and deletion can take place at both the front and rear
ends of the queue.
**queue** is a linear data structure that follows the First-In-First-Out (FIFO) principle. This
means that the first element added to the queue will be the first one to be removed. Think of it
like a line at a grocery store: the person who arrives first is the first one to be served.
● Dequeue (Delete): Removes and returns the element from the front of the queue.
● Peek: Returns the element at the front of the queue without removing it.
### Definition
1. **Print Queue**: When multiple documents are sent to a printer, they are placed in a queue.
The first document sent is printed first, while the others wait their turn.
2. **Task Scheduling**: Operating systems use queues to manage processes. Tasks or processes
are added to a queue and executed in the order they arrive.
3. **Call Centers**: Incoming calls are placed in a queue and are attended to in the order they
are received.
### Applications
1. **Breadth-First Search (BFS)**: Queues are used in BFS algorithms to explore nodes in a
graph level by level.
2. **Task Scheduling**: Operating systems and real-time systems use queues to schedule tasks
and manage process execution.
3. **Buffering**: In data streaming or IO operations, queues are used to manage data being read
from or written to hardware devices.
4. **Handling Requests**: Web servers often use queues to manage incoming client requests,
processing them one by one.
### Operations
3. **Peek/Front**: Access the element at the front of the queue without removing it.
- **Time Complexity**: O(1)
// Global variables
int front = 0;
int rear = -1;
int size = 0;
int arr[MAX];
// Function prototypes
int isEmpty();
int isFull();
void enqueue(int value);
int dequeue();
int peek();
int queueSize();
void displayQueue();
int main() {
int choice, value;
do {
printf("\nQueue Operations Menu:\n");
printf("1. Enqueue\n");
printf("2. Dequeue\n");
printf("3. Peek\n");
printf("4. Check if Empty\n");
printf("5. Check Size\n");
printf("6. Display Queue\n");
printf("7. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
if (isFull()) {
printf("Queue is full. Cannot enqueue.\n");
} else {
printf("Enter value to enqueue: ");
scanf("%d", &value);
enqueue(value);
printf("Enqueued %d\n", value);
}
break;
case 2:
if (isEmpty()) {
printf("Queue is empty. Cannot dequeue.\n");
} else {
value = dequeue();
printf("Dequeued %d\n", value);
}
break;
case 3:
if (isEmpty()) {
printf("Queue is empty. Nothing to peek.\n");
} else {
value = peek();
printf("Front element is %d\n", value);
}
break;
case 4:
if (isEmpty()) {
printf("Queue is empty.\n");
} else {
printf("Queue is not empty.\n");
}
break;
case 5:
printf("Queue size is %d\n", queueSize());
break;
case 6:
displayQueue();
break;
case 7:
printf("Exiting...\n");
break;
default:
printf("Invalid choice. Please try again.\n");
break;
}
} while (choice != 7);
return 0;
}
// Check if the queue is empty
int isEmpty() {
return (size == 0);
}
// Check if the queue is full
int isFull() {
return (size == MAX);
}
// Enqueue an element
void enqueue(int value) {
rear = (rear + 1) % MAX;
arr[rear] = value;
size++;
}
// Dequeue an element
int dequeue() {
int value = arr[front];
front = (front + 1) % MAX;
size--;
return value;
}
// Peek at the front element
int peek() {
return arr[front];
}
// Get the current size of the queue
int queueSize() {
return size;
}
// Display the elements of the queue
void displayQueue() {
if (isEmpty()) {
printf("Queue is empty.\n");
return;
}
printf("Queue elements: ");
for (int i = 0; i < size; i++) {
printf("%d ", arr[(front + i) % MAX]);
} printf("\n"); }
**Pseudo-code:**
InitializeQueue:
front = 0
rear = -1
size = 0
arr = array of size MAX
#### 2. Enqueue (Add an Element to the Queue)
**Algorithm:**
1. Check if the queue is full by comparing `size` with `MAX`.
- If full, print "Queue is full" and exit.
2. Increment `rear` by 1 and wrap around using modulo `MAX`.
3. Insert the new element at `arr[rear]`.
4. Increment `size` by 1.
**Pseudo-code:**
Enqueue(value):
if size == MAX:
print "Queue is full"
return
rear = (rear + 1) % MAX
arr[rear] = value
size = size + 1
#### 3. Dequeue (Remove an Element from the Queue)
**Algorithm:**
1. Check if the queue is empty by comparing `size` with 0.
- If empty, print "Queue is empty" and exit.
2. Retrieve the element from `arr[front]`.
3. Increment `front` by 1 and wrap around using modulo `MAX`.
4. Decrement `size` by 1.
5. Return the retrieved element.
**Pseudo-code:**
Dequeue():
if size == 0:
print "Queue is empty"
return
value = arr[front]
front = (front + 1) % MAX
size = size - 1
return value
#### 4. Peek (View the Front Element of the Queue)
**Algorithm:**
1. Check if the queue is empty by comparing `size` with 0.
- If empty, print "Queue is empty" and exit.
2. Retrieve and return the element at `arr[front]`.
**Pseudo-code:**
```plaintext
Peek():
if size == 0:
print "Queue is empty"
return
return arr[front]
**Algorithm:**
1. Return `true` if `size` is 0; otherwise, return `false`.
**Pseudo-code:**
```plaintext
IsEmpty():
return (size == 0)
**Algorithm:**
1. Return `true` if `size` is equal to `MAX`; otherwise, return `false`.
**Pseudo-code:**
```plaintext
IsFull():
return (size == MAX)
**Algorithm:**
1. Return the current `size` of the queue.
**Pseudo-code:**
```plaintext
QueueSize():
return size
**Pseudo-code:**
```plaintext
DisplayQueue():
if size == 0:
print "Queue is empty"
return
for i from 0 to size - 1:
index = (front + i) % MAX
print arr[index]