Skip to main content
  1. Portfolios/
  2. Datastructures & Algorithms in Elixir/

Stack

·634 words·3 mins· loading · loading · ·
Programming
Ch Virinchi
Author
Ch Virinchi
Elixir programmer, rocket propulsion enthusiast. Web Application developer.
Table of Contents
Elixir DSA - This article is part of a series.
Part 5: This Article

The Stack is a special data structure. We use lists to augment it and everything is the same, except for 3 small constraints -

  1. Data can only be inserted at the end of the stack
  2. Data can only be deleted from the end of the stack
  3. Only the last element of the stack can be accessed

A quick note- The terms end and start will change depending on which direction you’re parsing the array. This might lead to confusion. The solution is, it doesn’t matter which direction you parse it, as long as you are consistent.

In Elixir, prepending to a list is extremely efficient and takes only linear time (O(1)). For this reason, unless otherwise mentioned, we will always prepend to a list and pop the first element only.

Now you might be wondering, what do these additional constraints offer that makes stack so powerful?

Understanding the Stack

Stack simply follows the LIFO (Last In First Out) principle. Imagine this to be the naughty kids in school. They’ll be the last to enter the class, and the first to leave. We are only concerned about the naughty kids. This means we can only read/pop/append items at the end of the stack.

This behavior is extremely useful in day-to-day programs as demonstrated by the following examples-

  • The Undo action is a good example of stack. We keep appending the list of changes in a document to the stack, and just delete the last change to undo the previous action

  • Another example is the valid parentheses problem. Given a string, we are required to check if the parentheses are in the correct order & form a valid pair. We append each opening parenthesis to the stack, and delete it if the next character is its corresponding closing one. Finally, if the stack is empty, given string is valid.

  • A fun exercise would be to implement the Towers of Hanoi problem.

  • Most programming languages use Stack to implement recursion under the hood. Each recursive call is added to the stack until the base case. Then each functions value is interpolated and popped from the stack.

A few fun problems solved using stack are checked into this repo for reference. Do read.

Implementation

For conciseness & simplicity, we’ll implement the stack as a module, and reference functions from it. As discussed above, stack is just a simple list, with added constraints. Since we can only interact with a stack to append, read and pop the last element, we’ll name our functions as push/2, peek/1 and pop/1.

The Stack module

The push/2 function

To append items at the end of the stack, we only need 2 things - the stack to append to, and the item to append. That’s a one liner -

def push(stack, item), do: [item | stack]

Prepending to a list is extremely efficient in Elixir, which takes linear time (O(1)) under the hood.

The peek/1 function

Since we can only read the first element, we need to pass in only the stack.

def peek([]), do: nil
def peek([head | _]), do: head

The pop/1 function

To pop the last element, we need to pass in only the stack.

def pop([]), do: []
def pop([_ | tail]), do: tail

The Stack module

defmodule Stack do
  def push(stack, item), do: [item | stack]

  def peek([]), do: nil
  def peek([head | _]), do: head

  def pop([]), do: []
  def pop([_ | tail]), do: tail
end

To maintain consistency, we’ll always alias in this module and interact with stacks using these functions only. That’ll keep the list from mutating accidentally.

There are many interesting problems solved using Stacks. It is useful to go through the code and understand the solutions. I tried to solve a good number of them. All the solutions are checked into this Git Repo
Elixir DSA - This article is part of a series.
Part 5: This Article

Related

Merge Sort
·875 words·5 mins· loading · loading
Programming
Merge sort is a divide an conquer algorithm that relies solely on recursion to sort a list, making it the ideal algorithm to implement in Elixir.
Quick Sort
·1095 words·6 mins· loading · loading
Programming
Quick Sort is the go-to sorting algorithm for many programmers due to its efficiency and elegance. Lets implement it in Elixir-
Insert Sort
·976 words·5 mins· loading · loading
Programming
Insert sort is the defacto algorithm most programmers get started on their journey with. Lets see how to implement it in Elixir.