Module 2
Module 2
Module 2
STACKS
STACKS
• Stack has one end. It contains only one pointer top pointer pointing to the
topmost element of the stack. Whenever an element is added in the stack, it is
added on the top of the stack, and the element can be deleted only from the stack.
• stack can be defined as a container in which insertion and deletion can be done
from the one end known as the top of the stack.
Stack operations
• push(): When we insert an element in a stack then the operation is
known as a push. If the stack is full then the overflow condition
occurs.
• pop(): When we delete an element from the stack, the operation is
known as a pop. If the stack is empty means that no element exists in
the stack, this state is known as an underflow state.
• isEmpty(): It determines whether the stack is empty or not.
• isFull(): It determines whether the stack is full or not.
• display(): It prints all the elements available in the stack.
PUSH Operation
• Before inserting an element in a stack, we check whether the stack is
full.
• If we try to insert the element in a stack, and the stack is full, then
the overflow condition occurs.
• When we initialize a stack, we set the value of top as -1 to check that
the stack is empty.
• When the new element is pushed in a stack, first, the value of the top
gets incremented, i.e., top=top+1, and the element will be placed at
the new position of the top.
• The elements will be inserted until we reach the max size of the stack.
void push() //Inserting element into the stack
{
if(top==(max_size-1))
{
printf("\nStack Overflow:");
}
else
{
printf("Enter the element to be inserted:\t");
scanf("%d",&item);
top=top+1;
stack[top]=item;
}
}
POP operation
• Before deleting the element from the stack, we check whether the
stack is empty.
• If we try to delete the element from the empty stack, then
the underflow condition occurs.
• If the stack is not empty, we first access the element which is pointed
by the top
• Once the pop operation is performed, the top is decremented by 1,
i.e., top=top-1.
void pop() //deleting an element from the stack
{
if(top==-1)
{
printf("Stack Underflow:");
}
else
{
item=stack[top];
top=top-1;
}
}
Stack display()
void display()
{
int i;
top=temp;
if(top==-1)
{
printf("\nStack is Empty:");
}
else
{
printf("\nThe stack elements are:\n" );
for(i=top;i>=0;i--)
{
printf("%d\n",stack[i]);
}
}
Conversion from infix to postfix
Evaluation of suffix/postfix
1.While reading the expression from left to right, push the element in the stack
if it is an operand.
2.Pop the two operands from the stack, if the element is an operator and then
evaluate it.
3.Push back the result of the evaluation. Repeat it till the end of the expression.
Infix Expression: (A+B)+C-(D-E)^F
Prefix to infix
• Iterate the given expression from right to left (in reverse order), one
character at a time
1.If character is operand, push it to stack.
2.If character is operator,
1. pop operand from stack, say it’s s1.
2. pop operand from stack, say it’s s2.
3. perform (s1 operator s2) and push it to stack.
3.Once the expression iteration is completed, initialize result string and
pop out from stack and add it to result.
4.Return the result.
Recursion
If I type value as 8, it will read it as the character ASCII value of 56. If I also type value 9, it will read
it as the character ASCII value of 57.
If you add them, the program will do 58 + 59 and give you the wrong answer. So to actually get to
8 from 56, you subtract 48. 56 – 48 = 8. And 57 – 48 = 9.
So after converting the ASCII values to the actual integer value, you can proceed with 8 + 9 = 17.
Ackermann function
Use of Ackermann function
int main()
{
int num1, num2, hcf, lcm;
int factorial(int n) {
//base case
if(n == 0) {
return 1;
} else {
return n * factorial(n-1);
}
}
int fibbonacci(int n) {
if(n == 0){
return 0;
} else if(n == 1) {
return 1;
} else {
return (fibbonacci(n-1) + fibbonacci(n-2));
}
}
int main() {
int n = 5;
int i;
for(i = 0;i<n;i++) {
printf("%d ",fibbonacci(i));
}
}
Factorial of 5: 120
Fibonacci of 5: 0 1 1 2 3
QUEUES
• A queue is a linear data structure that stores the
elements sequentially. It uses the FIFO approach (First In
First Out) for accessing elements.
Applications of Queue
1.Queues are widely used as waiting lists for a single shared resource
like printer, disk, CPU.
2.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.
3.Queues are used as buffers in most of the applications like MP3 media
player, CD player, etc.
4.Queue are used to maintain the play list in media players in order to
add and remove the songs from the play-list.
5.Queues are used in operating systems for handling interrupts.
QUEUE
• For example, people waiting in line for a rail ticket form a queue.
Basic Operations of Queue
• Peek: Get the value of the front of the queue without removing it
Working of Queue
• If the first three elements are deleted from the Queue, we cannot insert
more elements even though the space is available in a Linear Queue.
• In this case, the linear Queue shows the overflow condition as the rear
is pointing to the last element of the Queue.
Enqueue Operation
front = 0;
printf("Enter element which is to be inserted ");
scanf("%d", &element);
rear = rear + 1;
queue_array[rear] = element;
}
} /* End of insert() */
Dequeue Operation
• for the last element, reset the values of FRONT and REAR to -1
void delete()
{
if (front == - 1 || front > rear)
{
printf("Queue is empty we cannot delete an element \
n");
return ;
}
else
{
printf("Element deleted from queue is : %d\n",
queue_array[front]);
front = front + 1;
}
} /* End of delete()
void display()
{
int i;
if (front==-1 || front > rear)
printf("Queue is empty \n");
else
{
printf("Elements of Queue are: \n");
for (i = front; i <= rear; i++)
printf("%d ", queue_array[i]);
printf("\n");
}
}
Circular queue
• To overcome this problem, we can use multiple stack. For this, we have used a single array having
more than one stack. The array is divided for multiple stacks.
• Suppose there is an array STACK[n] divided into two stack STACK A and STACK B, where n = 10.
• STACK A expands from the left to the right, i.e., from 0th element.
• STACK B expands from the right to the left, i.e., from 10th element.
• The combined size of both STACK A and STACK B never exceeds 10.
Stacks vs multiple stacks
• Storage Efficiency: When we create a stack using a single array, it may
not be sufficient to store a large amount of data. By employing multiple
stacks within the same array, we can efficiently utilize memory space.
Each stack operates independently, allowing us to manage different data
sets effectively12.
• Directional Growth: When using two stacks within the same array, they
can grow in opposite directions. For instance:
• Insertion at front
• Insertion at rear
• Deletion at front
• Deletion at rear
Insertion at the front end
• in this operation, the element is inserted from the front end of the
queue. Before implementing the operation, we first have to check
whether the queue is full or not. If the queue is not full, then the
element can be inserted from the front end by using the below
conditions -
• If the queue is empty, both rear and front are initialized with 0. Now,
both will point to the first element.
• Otherwise, check the position of the front if the front is less than 1
(front < 1), then reinitialize it by front = n - 1, i.e., the last index of
the array.
Insertion at the rear end
• In this operation, the element is inserted from the rear end of the
queue. Before implementing the operation, we first have to check
again whether the queue is full or not. If the queue is not full, then the
element can be inserted from the rear end by using the below
conditions –
• If the queue is empty, both rear and front are initialized with 0. Now,
both will point to the first element.
• Otherwise, increment the rear by 1. If the rear is at last index (or size -
1), then instead of increasing it by 1, we have to make it equal to 0.
Deletion at the front end
• in this operation, the element is deleted from the front end of the
queue. Before implementing the operation, we first have to check
whether the queue is empty or not.
• If the queue is empty, i.e., front = -1, it is the underflow condition, and
we cannot perform the deletion. If the queue is not full, then the
element can be inserted from the front end by using the below
conditions –
• If the deque has only one element, set rear = -1 and front = -1.
• Else if front is at end (that means front = size - 1), set front = 0.
• Else increment the front by 1, (i.e., front = front + 1).
Deletion at the rear end
• In this operation, the element is deleted from the rear end of the queue.
Before implementing the operation, we first have to check whether the
queue is empty or not.
• If the queue is empty, i.e., front = -1, it is the underflow condition, and
we cannot perform the deletion.
• If the deque has only one element, set rear = -1 and front = -1.
• If rear = 0 (rear is at front), then set rear = n - 1.
• Else, decrement the rear by 1 (or, rear = rear -1).
Priority Queue
• Priority is a special type of data structure in which items can be
inserted or deleted based on the priority. The priority of the elements
in a priority queue determines the order in which elements are served
(i.e., the order in which they are removed).
• Properties of Priority Queue
• Every item has a priority associated with it.
• An element with high priority is dequeued before an element with low
priority.
• If two elements have the same priority, they are served according to
their order in the queue.
Types of Priority Queue
Step 1: In the list, lower priority number is 1, whose data value is 300, so it will be inserted in the
list as shown in the below diagram:
Step 2: After inserting 300, priority number 2 is having a higher priority, and data values
associated with this priority are 200 and 100. So, this data will be inserted based on the FIFO
principle; therefore 200 will be added first and then 100.
Step 3: After inserting the elements of priority 2, the next higher priority number is 4 and data
elements associated with 4 priority numbers are 400, 500, 700. In this case, elements would be
inserted based on the FIFO principle; therefore, 400 will be added first, then 500, and then 700.
Step 4: After inserting the elements of priority 4, the next higher priority number is 5, and the
value associated with priority 5 is 600, so it will be inserted at the end of the queue.
Real-time application of Queue:
• The operations such as insertion and deletion of elements from the middle are
time consuming.
• Limited Space.
• In a classical queue, a new element can only be inserted when the existing
elements are deleted from the queue.
• Simple implementation.
much as the queue length, you have to know the maximum size
beforehand.
Applications of Deque:
• You are able to add and remove items from the both front and back of
the queue.
• Deques are faster in adding and removing the elements to the end or
beginning.
• Deque has no fixed limitations for the number of elements they may
contain. This interface supports capacity-restricted deques as well as
the deques with no fixed size limit.