Stack Data Structure: Implementation and Applications with a Focus on Call Stack

Abdul Syed
2 min readJul 20, 2023

Introduction

The stack is a linear data structure that operates on the principle of Last In, First Out (LIFO). This unique characteristic ensures that the most recently added (pushed) element is the first one to be removed (popped). The simplicity and efficiency of the stack make it a popular choice in numerous applications. This paper aims to explore these applications and provide hands-on coding examples for better comprehension.

Applications of Stack Data Structure

Stacks, despite their simple structure, provide solutions to a wide range of complex problems. The following are some of the major applications:

Expression Evaluation and Conversion

Stacks are essential tools for evaluating arithmetic expressions and converting between infix, postfix, and prefix notations.

Consider the evaluation of a postfix expression:

def evaluate_postfix(expression):
stack = []

for character in expression:
if character.isdigit():
stack.append(int(character))
else:
val1 = stack.pop()
val2 = stack.pop()

switcher = {
'+': val2 + val1,
'-': val2 - val1,
'*': val2 * val1,
'/': val2 / val1,
'^': val2**val1
}

stack.append(switcher.get(character))

return stack.pop()

print(evaluate_postfix("231*+9-")) # returns -4

Syntax Parsing

Compilers use stacks to parse the syntax of expressions, check for balanced parentheses, and determine the proper usage of operators.

Consider the task of checking for balanced parentheses:

def is_balanced(expression):
stack = []

for char in expression:
if char in ["(", "{", "["]:
stack.append(char)
else:
if not stack:
return False
current_char = stack.pop()
if current_char == '(':
if char != ")":
return False
if current_char == '{':
if char != "}":
return False
if current_char == '[':
if char != "]":
return False

if stack:
return False
return True

print(is_balanced("{[]{()}}")) # returns True
print(is_balanced("[{}{})(]")) # returns False

Undo Mechanism

Stacks provide the underlying functionality for the ‘undo’ mechanism in many software applications.

Consider a simple undo mechanism in a text editor:

class TextEditor:
def __init__(self):
self.text_stack = []
self.undo_stack = []

def insert(self, text):
self.text_stack.append(text)
self.undo_stack.append(-len(text))

def delete(self, k):
text = self.text_stack[-k:]
self.text_stack = self.text_stack[:-k]
self.undo_stack.append(text)

def undo(self):
action = self.undo_stack.pop()
if type(action) == int:
self.text_stack = self.text_stack[:action]
else:
self.text_stack += action

editor = TextEditor()
editor.insert('Hello')
editor.insert(' World')
print(''.join(editor.text_stack)) # prints "Hello World"
editor.undo()
print(''.join(editor.text_stack)) # prints "Hello"

Conclusion

The stack data structure, in its elegant simplicity, serves as a powerful tool in solving complex problems in computer science. The real power of stacks lies in their LIFO property, which enables efficient solutions in areas like expression evaluation, syntax parsing, and the undo mechanism. Understanding the stack’s properties, together with practical coding examples, provides a robust foundation for efficient problem-solving in numerous applications.

--

--