hakk

software development, devops, and other drivel
Tree lined path

Stack Data Structure

The stack data structure is a fundamental abstract data type commonly used in computer science and software engineering. It follows the Last-In, First-Out (LIFO) principle, meaning that the last element added to the stack is the first one to be removed. Think of it like a stack of plates: you can only add or remove plates from the top of the stack.

Stack of pancakes
Stack of pancakes

Basic Operations

  • Push: Adding an element to the top of the stack.
  • Pop: Removing the top element from the stack.
  • Peek (or Top): Viewing the top element of the stack without removing it.
  • isEmpty: Checking if the stack is empty.
  • Size: Returning the number of elements currently in the stack.

Implementations

  • Stacks can be implemented using various data structures, including arrays and linked lists.
  • Arrays are commonly used for implementing stacks due to their simplicity and constant-time access to elements.
  • Linked lists can also be used, providing dynamic memory allocation and flexibility.

A stack implemented using an array

A stack implemented using a Linked List.

Time Complexity

Array Implementation

For the list/array/vector implementation of the stack the average time complexity of the push and pop operations are O(1). However, if the array needs to be resized the complexity will become O(n) where n is the number of elements in the stack.

Linked List Implementation

A summarization of the best, average, and worst-case time and space complexities for common operations on the stack data structure using a linked list:

OperationBest CaseAverage CaseWorst CaseSpace Complexity
Push(O(1))(O(1))(O(1))(O(1))
Pop(O(1))(O(1))(O(1))(O(1))
Peek(O(1))(O(1))(O(1))(O(1))
isEmpty(O(1))(O(1))(O(1))(O(1))
Size(O(1)) or (O(n))(O(1)) or (O(n))(O(1)) or (O(n))(O(1)) or (O(n))

Explanation:

  • Push: Adding an element to the top of the stack involves inserting the element at the top position. This operation has a constant time complexity of (O(1)) in all cases. The space complexity is also (O(1)) since only one element is added.

  • Pop: Removing the top element from the stack involves deleting the element at the top position. This operation has a constant time complexity of (O(1)) in all cases. The space complexity is also (O(1)) since only one element is removed.

  • Peek: Viewing the top element of the stack without removing it has a constant time complexity of (O(1)) in all cases. This operation does not modify the stack, so the space complexity is (O(1)).

  • isEmpty: Checking if the stack is empty involves verifying whether the stack contains any elements. This operation has a constant time complexity of (O(1)) in all cases. The space complexity is also (O(1)) since it only requires checking a flag or variable.

  • Size: Determining the number of elements in the stack depends on the underlying implementation.

    • For an array-based implementation where the size is maintained explicitly, both the best, average, and worst-case time complexities for the Size operation are (O(1)). The space complexity is also (O(1)) since the size variable is maintained separately.
    • For a linked list-based implementation, traversing the entire linked list to count the elements results in a time complexity of (O(n)) in the best, average, and worst cases. The space complexity is also (O(n)) since the stack size is directly proportional to the number of elements stored in the linked list.

In summary, stack operations are typically very efficient, with constant time complexities for basic operations like Push, Pop, Peek, and isEmpty. The space complexity depends on the underlying implementation and whether the size of the stack is maintained explicitly.

Applications of Stack Data Structure

A stack is a simple but very powerful data structure and has many uses. Some of those uses are:

  • Arithmetic Expression Evaluation, a stack is very effective in evaluating arithmetic expressions.
  • They can also be used for Backtracking. Backtracking is an algorithmic technique that is used to search all possible solutions for a problem.
  • Tracking function calls, whenever a call is made from one function to another the address of the calling function gets stored on the stack.

Challenges

  • Implement a queue using the stack data structure.
  • Check valid parentheses.
  • Reverse a string.