There are two ways to implement a stack:
class Stack:
def __init__(self):
self.stack = []
def is_empty(self):
return len(self.stack) == 0
def push(self, data):
self.stack.append(data)
def pop(self):
if(self.is_empty()):
return "Underflow"
return self.stack.pop()
def top(self):
if(self.is_empty()):
return "Underflow"
return self.stack[-1]
print("Example:- Array Implementation of Stack.")
my_stack = Stack()
print("Push: 4, 1, 7, 8 to stack.")
my_stack.push(4)
my_stack.push(1)
my_stack.push(7)
my_stack.push(8)
print("Pop the first element: {}".format(my_stack.pop()))
print("Top element in stack: {}".format(my_stack.top()))
print("Is stack empty? {}".format(my_stack.is_empty()))
Output:
class StackNode:
def __init__(self, data):
self.data = data
self.next = None
class Stack:
def __init__(self):
self.head = None
def is_empty(self):
return True if self.head is None else False
def push(self, data):
new_stack_node = StackNode(data)
new_stack_node.next = self.head
self.head = new_stack_node
def pop(self):
if(self.head is None):
return "Underflow"
temp = self.head
self.head = self.head.next
return temp.data
def top(self):
if(self.head is None):
return "Underflow"
return self.head.data
print("Example:- Linked List Implementation of Stack.")
my_stack = Stack()
print("Push: 4, 1, 7, 8 to stack.")
my_stack.push(4)
my_stack.push(1)
my_stack.push(7)
my_stack.push(8)
print("Pop the first element: {}".format(my_stack.pop()))
print("Top element in stack: {}".format(my_stack.top()))
print("Is stack empty? {}".format(my_stack.is_empty()))
Output:
Given an infix expression conversation it to a postfix operation.
Example:
Input:
a+b*(c-d)
Output:abcd-*+
Input:
a+b*(c^d-e)^(f+g*h)-i
Output:abcd^e-fgh*+^*+i-
Infix expression: ** The expression of the form **a op b. When an operator is in-between every pair of operands.
Postfix expression: The expression of the form a b op. When an operator is followed for every pair of operands.
Why postfix representation of the expression?
def infix_to_postfix(expr):
operator_precedence = {'+':1, '-':1, '*':2, '/':2, '%':2, '^':3}
# operator_stack
stack = []
# Start the scan from left to right
for char in expr:
# If scanned char is not an operand, then output it.
if char.isalpha():
print("{}".format(char), end="")
# Else if the scanned character is an ‘(‘, push it to the stack.
elif(char == "("):
stack.append(char)
# If the scanned character is an ‘)’, pop and output from the stack until an ‘(‘ is encountered.
elif(char == ")"):
while(len(stack)>0 and stack[-1] != "("):
print("{}".format(stack.pop()), end="")
stack.pop()
# Pop the operator from the stack until operator_precedence[char] <= operator_precedence[stack[-1]]
# Push the scanned operator to the stack
else:
while(len(stack)>0 and stack[-1]!="("
and operator_precedence[char] <= operator_precedence[stack[-1]]):
print("{}".format(stack.pop()), end="")
# If either stack is empty or precedence of scanned opeartor is greater
# than the top of stack, Push it to stack
stack.append(char)
# Pop and output from the stack until it is not empty.
while(len(stack)>0):
print("{}".format(stack.pop()), end="")
print()
print("Example-1: Infix-to-postfix")
infix_to_postfix("a+b*(c-d)")
print("\nExample-2: Infix-to-postfix")
infix_to_postfix("a+b*(c^d-e)^(f+g*h)-i")
Output:
Evaluate the value of the postfix expression.
Example:
Input:
12 3 *
Output:36
Input:
2 3 10 * + 9 -
Output:23
Why postfix evaluation?
def evaluate_postfix(expression):
expr = expression.split()
stack = []
for i in expr:
if i.isdigit():
stack.append(i)
else:
val1 = stack.pop()
val2 = stack.pop()
stack.append(str(eval(val2 + i + val1)))
print(stack.pop())
print("Example-1: evaluate_postfix('12 3 *')")
evaluate_postfix('12 3 *')
print("Example-2: evaluate_postfix('2 3 10 * + 9 -')")
evaluate_postfix('2 3 10 * + 9 -')
Output:
Given an expression string exp , write a program to examine whether the pairs and the orders of "{", "}", "(", ")", "[", "]"
are correct in expression.
Example:
Input:
"[()]{}{[()()]()}"
Output: BalancedInput:
"[(])"
Output: Not Balanced
def check_balanced_bracket(expression):
stack = []
balanced = True
for bracket in expression:
# If current is opening bracket push closing bracket to stack
if bracket=='(':
stack.append(')')
elif bracket=='{':
stack.append('}')
elif bracket=='[':
stack.append(']')
# If current is not opening bracket or the bracket doesnt match the top of stack -> Unbalanced
elif not stack or stack.pop() != bracket:
balanced = False
break
# If Stack is empty it is balanced else not balanced
if stack or not balanced:
print("Not Balanced")
else:
print("Balanced")
print("Example-1: check_balanced_bracket('[()]{}{[()()]()}')")
check_balanced_bracket('[()]{}{[()()]()}')
print("\nExample-2: check_balanced_bracket('[(])')")
check_balanced_bracket('[(])')
Output:
Given an array, print the Next Greater Element (NGE) for every element. The Next greater Element for an element x is the first greater element on the right side of x in array. Elements for which no greater element exist, consider next greater element as -1.
Example-Run:
def next_greater_for_every_element(arr):
n = len(arr)
stack = []
# Push the first element to stack
stack.append(arr[0])
print("Element -- NGE")
# Iterate for rest of the elements
for i in range(1, n):
current = arr[i]
# If stack is not empty, then pop an element from stack as popped_element
if stack:
popped_element = stack.pop()
# If popped_element is smaller than current, then current is NGE for popped element
# keep popping while popped elements are smaller than current and stack is not empty
while popped_element < current:
print("{} -------> {}".format(popped_element, current))
if not stack:
break
popped_element = stack.pop()
# If popped_element is greater than next, then push the popped_element back to stack
if popped_element > current:
stack.append(popped_element)
# Push current to stack so that we can find next greater for it.
stack.append(current)
# After iterating over the loop, the remaining elements in stack do not have the next greater
# so -1 for them
while stack:
popped_element = stack.pop()
current = -1
print("{} -------> {}".format(popped_element, current))
print("Example-1: next_greater_for_every_element([4, 5, 2, 25])")
next_greater_for_every_element([4, 5, 2, 25])
print("\nExample-2: next_greater_for_every_element([13, 7, 6, 12])")
next_greater_for_every_element([13, 7, 6, 12])
print("\nExample-3: next_greater_for_every_element([11, 13, 21, 3])")
next_greater_for_every_element([11, 13, 21, 3])
Output:
← Previous: Linked List Next: Queue →