0% found this document useful (0 votes)
6 views5 pages

Stacks (Without Comments and Testing)

The document defines a Stack class implemented using a linked list, with methods for standard stack operations such as push, pop, peek, and checking if the stack is empty. It also includes additional functionalities like reversing the stack, checking for balanced parentheses, converting prefix to postfix expressions, and solving the Tower of Hanoi problem. The Node class is used to represent each element in the stack, encapsulating data and a reference to the next node.

Uploaded by

yuzi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views5 pages

Stacks (Without Comments and Testing)

The document defines a Stack class implemented using a linked list, with methods for standard stack operations such as push, pop, peek, and checking if the stack is empty. It also includes additional functionalities like reversing the stack, checking for balanced parentheses, converting prefix to postfix expressions, and solving the Tower of Hanoi problem. The Node class is used to represent each element in the stack, encapsulating data and a reference to the next node.

Uploaded by

yuzi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

class Node:

def __init__(self, data):


self.__data = data
self.__next = None

@property
def data(self):
return self.__data

@data.setter
def data(self, data):
self.__data = data

@property
def next(self):
return self.__next

@next.setter
def next(self, value):
self.__next = value

class Stack:
def __init__(self):
self.__top = None
self.__size = 0

def push(self, data):

new_node = Node(data)

if self.__top is None:
self.__top = new_node

else:
new_node.next = self.__top
self.__top = new_node

self.__size += 1
print(f"Pushed: {data}")

def pop(self):

if self.__top is None:
print("Stack underflow! Cannot pop from an empty stack.")
return None

popped_data = self.__top.data
self.__top = self.__top.next
self.__size -= 1
print(f"Popped: {popped_data}")

return popped_data

def peek(self):

if self.__top is None:
print("Stack is empty! Nothing to peek.")
return None
return self.__top.data

def is_empty(self):

if self.__top is None:
print("Stack is empty.")
return True

else:
print("Stack is not empty.")
return False

def get_size(self):

return self.__size

def display(self):

if self.__top is None:
print("Stack is empty!")
return

current = self.__top

print("Stack elements:")

while current:
print(current.data, end=" -> ")
current = current.next

print("None")

def clear(self):

self.__top = None
self.__size = 0
print("Stack cleared!")

def search(self, value):

current = self.__top
position = 0

while current:

if current.data == value:
print(f"Element '{value}' found at position {position}")
return position

current = current.next
position += 1

print(f"Element '{value}' not found in the stack.")

return -1

def reverse(self):
previous = None
current = self.__top

while current:

next_node = current.next
current.next = previous
previous = current
current = next_node

self.__top = previous

print("Stack reversed!")

# Palindrome Checker #1: Checks the passed data is palindrome or not


def is_palindrome(self, input_string):

word = input_string.lower()

for char in word:


self.push(char)

reversed_string = ""
while not self.is_empty():
reversed_string += self.pop()

return word == reversed_string

# Palindrome Checker #2: Checks the whole data in the stacks

# def is_palindrome(self):
# if self.__top is None:
# print("Stack is empty! Cannot check for palindrome.")
# return False
#
# forward = ""
# reverse = ""
# current = self.__top
#
# while current:
# char = current.data
#
# lower_char = char.lower()
#
# forward = forward + lower_char
#
# reverse = lower_char + reverse
#
# current = current.next
#
# if forward == reverse:
# print("The stack is a palindrome.")
# return True
#
# else:
# print("The stack is not a palindrome.")
# return False

def is_parenthesis_balanced(self, input_string):


for char in input_string:

if char == '(' or char == '{' or char == '[':


self.push(char)

elif char == ')' or char == '}' or char == ']':

if self.is_empty():
return False

top_char = self.pop()

if (char == ')' and top_char != '(') or \


(char == '}' and top_char != '{') or \
(char == ']' and top_char != '['):
return False

return self.is_empty()

def is_operand(self, char):

return ('a' <= char <= 'z') or ('A' <= char <= 'Z') or ('0' <= char <= '9')

def prefix_to_postfix(self, expression):

for symbol in reversed(expression):

if self.is_operand(symbol):
self.push(symbol)

else:

operand1 = self.pop()
operand2 = self.pop()

if operand1 is None or operand2 is None:


print("Invalid prefix expression")
return ""

new_expr = operand1 + operand2 + symbol


self.push(new_expr)

return self.pop()

def postfix_to_prefix(self, expression):

for symbol in expression:

if self.is_operand(symbol):
self.push(symbol)

else:

operand2 = self.pop()
operand1 = self.pop()

if operand1 is None or operand2 is None:


print("Invalid postfix expression")
return ""

new_expr = symbol + operand1 + operand2


self.push(new_expr)

return self.pop()

def tower_of_hanoi(self, n, source, target, auxiliary):

if n == 1:

disk = source.pop()
target.push(disk)
print(f"Move disk {disk} from Source to Target")
return

self.tower_of_hanoi(n - 1, source, auxiliary, target)

disk = source.pop()
target.push(disk)
print(f"Move disk {disk} from Source to Target")

self.tower_of_hanoi(n - 1, auxiliary, target, source)

You might also like