DS Unit1 Stacks
DS Unit1 Stacks
STACK
S
Need of Stack
Operations on stack
Implementation of Stack
Stack VS Array
Push stack algo
Stack POP
Stack POP algo
Stack peek and traverse
Solution
We can implement the stack using the linked list.
In the linked list, we can change its size at runtime.
In the stack Implementation, a stack contains a top pointer. which is the “head” of the
stack where pushing and popping items happens at the head of the list.
Understanding Stack Implementation Using Singly Linked List
When implementing a stack using singly linked list, it is essential to consider the standard operations of push, pop,
and peek. The push operation involves adding an element to the top of the stack, while the pop operation removes
the top element from the stack. The peek operation returns the value of the top element without removing it.
Suppose we insert elements 4, 3, 2, and 1 into the stack using the push operation. In push operation elements are
added to the top of the stack. In other words, the last element to be pushed onto the stack becomes the top
element, while the first element to be pushed becomes the bottom element. So, when elements are pushed onto
the stack in that order, the top of the stack will contain element 1, and the bottom of the stack will contain element
4.
When we want to access the elements in the stack, we can only access them in a LIFO (Last-In-First-Out) manner,
meaning that we can only access the top element first, followed by the second-to-top element, and so on. In other
words, we must first remove the top element using the pop operation to access the next element in the stack.
So, to access the elements in the order 1, 2, 3, and 4, we would need to pop the elements from the stack in reverse
order, starting with 1, then 2, then 3, and finally 4. This is because the top of the stack currently contains element 1,
so it must be popped first to access the next element, which is 2. The below image shows how these elements are
represented in a singly linked list.
Stack as a linked list
#include <bits stdc++.h="">
// Using this function we will be checking
using namespace std;
whether the stack is empty or not
struct Node
int isEmpty()
{
{
int data;
return top == NULL;
struct Node* link;
}
};
// Using this function we will return the top
struct Node* top;
element of the stack
// Using this function we will be pushing
int peek()
elements into the stack
{
void push(int data)
if (!isEmpty())
{
return top->data;
struct Node* tem;
else
tem = new Node();
exit(1);
if (!tem)
}
{
cout << "\nHeap Overflow";
exit(1);
}
tem->data = data;
tem->link = top;
top = tem;
}
// Using this function we will pop the top else
element of the stack {
void pop() tem = top;
{ while (tem != NULL)
struct Node* tem; {
if (top == NULL) cout << tem->data << "-> ";
{ tem = tem->link; }}}
cout << "\nStack Underflow" << endl;
exit(1); int main()
} {
else push(4);
{ push(3);
tem = top; push(2);
top = top->link; push(1);
tem->link = NULL; display();
free(tem); }} cout << "\nTop element is "<< peek() <<
endl;
void display() pop();
{ pop();
struct Node* tem; cout<<"Stack after popping 2 times \n";
if (top == NULL) display();
{ cout << "\nTop element is "<< peek() <<
cout << "\nStack Underflow"; endl;
exit(1); return 0;
} }
Complexity Analysis of Stack Implementation
Using Singly Linked List
Let’s analyze the time and space complexity of each operation in the implementation of a stack using
linked list.
1.push() Operation:
Since we always add a new element at the top of the stack, this operation takes constant time. We only
need to allocate memory for the new node, set its data, and update the "next" pointer to the current
top of the stack.
Time complexity: O(1)
Space complexity: O(1)
We only allocate memory for the new node, so the space complexity of the push operation is constant.
2.pop() Operation:
Since we always remove the top element of the stack, this operation takes constant time. We only need
to update the "top" pointer to the next node and free the memory of the removed node.
Time complexity: O(1)
Space complexity: O(1)
We only remove a node from the stack, so the space complexity of the pop operation is constant.
3. peek() Operation:
This operation only returns the value of the top element, so it takes constant time.
Time complexity: O(1)
Space complexity: O(1)
We don’t need to allocate or remove any memory, so the space complexity of the peek operation is
constant.
Applications
Postfix notation (also known as Reverse Polish Notation) is a way to represent an expression, where operators follow
their corresponding operands.
Evaluating an expression represented as postfix notation can easily be done using the stack data structure.
Stack data structure is used to efficiently evaluate Postfix Expression.
Arithmetic Expression
Infix notation : <operands><operator><operands>
The virtues of postfix form include elimination of parentheses which signify priority of evaluation and
the elimination of the need to observe rules of hierarchy, precedence and associativity during
evaluation of the expression.
As Postfix expression is without parenthesis and can be evaluated as two operands and an operator at a
time, this becomes easier for the compiler and the computer to handle.
Evaluation of Arithmetic Expression
Evaluation of Postfix Expression
Step2.1:
if it is an operand, push it to the stack.
Step 2.2: If it is an operator, pop two operands from the stack. A is top
element and B is next to top element. Perform the operation (A op B) and
push the result back to the stack.
Step 3: Do this till all the elements of the expression are traversed and
return the top of stack which will be the result of the operation.
Evaluation of Prefix Expression
Infix to Postfix Conversion
Method 1:
Conversion from infix to postfix expression
• Initially we have a infix expression given to us to convert to postfix notation. The infix notation is parsed from left
to right, and then converted to postfix. Assume initially the postfix expression is empty, and we will fill the postfix
expression out with the following steps:
4. If we encounter an operator:-
• 4.1. If the operator has higher precedence than the one on top of the stack (We can compare ), we
push it in the stack.
• 4.2. If the operator has lower or equal precedence than the one on top of the stack, we keep
popping out and appending it to the postfix expression.
• When the last token of infix expression has been scanned, we pop the remaining elements from
stack and append them to our postfix expression.*
Algo for Infix to Postfix Conversion
using Stack
Infix to Postfix
Q.Convert infix expression to postfix
A recursive function is defined as a function that calls itself to solve a smaller version
of its task until a final call is made which does not require a call to itself. Since a
recursive function repeatedly calls itself, it makes use of the system stack to
temporarily store the return address and local variables of the calling function. Every
recursive solution has two major cases. They are
1.Base case, in which the problem is simple enough to be solved directly without
making any further calls to the same function.
2.Recursive case, in which first the problem at hand is divided into simpler sub-parts.
Second the function calls itself but with sub-parts of the problem obtained in the first
step. Third, the result is obtained by combining the solutions of simpler sub-parts.
Every recursive function must have at least one base case. Otherwise, the recursive
function will generate an infinite sequence of calls, thereby resulting in an error
condition known as an infinite stack.
Sum of natural number
using recursion
Types of Recursion
• Direct vs Indirect recursive function :
A function is said to be directly recursive if it explicitly calls itself.
A function is said to be indirectly recursive if it contains a call to another
function which ultimately calls it.