Stacks and Queues

CSCI 1913 – Introduction to Algorithms, Data Structures, and Program Development
Adriana Picoral

Stacks and Queues

  • intentionally restrictive
  • limit where you can add and remove elements

Stacks: Last-In, First-Out (LIFO)

Queues: First-In, First-Out (FIFO)

Stacks

  • add to the top (push)
  • remove from the top (pop)

Stacks

│         │
│         │
│         │  
├─────────┤    
│    D    │    ← top
├─────────┤   
│    C    │  
├─────────┤  
│    B    │ 
├─────────┤  
│    A    │  
└─────────┘  

Stacks

│    ↓    │
├─────────┤   
│    E    │    ← top
├─────────┤    
│    D    │
├─────────┤   
│    C    │  
├─────────┤  
│    B    │ 
├─────────┤  
│    A    │  
└─────────┘       

push(E)

Stacks

│    F    │    ← top
├─────────┤   
│    E    │
├─────────┤    
│    D    │
├─────────┤   
│    C    │  
├─────────┤  
│    B    │ 
├─────────┤  
│    A    │  
└─────────┘       

push(F)

Stacks

│         │
├─────────┤   
│    E    │    ← top
├─────────┤    
│    D    │
├─────────┤   
│    C    │  
├─────────┤  
│    B    │ 
├─────────┤  
│    A    │  
└─────────┘   

pop() → returns F
returns top and updates it (removes top)

Stacks

│         │
│         │
│         │  
├─────────┤    
│    D    │    ← top
├─────────┤   
│    C    │  
├─────────┤  
│    B    │ 
├─────────┤  
│    A    │  
└─────────┘  

pop() → returns E returns top and updates it (removes top)

Stacks

  • Can be implemented as arrays or linked lists
  • Features – push() and pop(), others?
  • LIFO – Last In, First Out

Write up a generic stack interface

Solution

public interface Stack<T> {

    /**
     * Stack is LIFO – Last In, First Ou
     * add a new value (with T data) to the top of the stack
     * @param data of generic type T
     */
    void push(T data);

    /**
     * Removes and returns the value at the top of the stack
     * @return the value stored in the node at the top of the stack
     */
    T pop();

    /**
     * Looks at the value at the top of the stack without removing it
     * @return the value stored in the node at the top of the stack
     */
    T top();
  
   /**
     * @return true if Stack is empty, false otherwise
     */
    boolean isEmpty();
}

Implementation of the Stack Interface

  • Stack as a linked list vs. array implementation
    • remember that stacks grow and shrink from only one end
  • Complexity – how does runtime compare?
  • Which is better (array or linked list)?

Stack Applications

  • Traversing a maze, a graph, or a tree
  • Expression evaluation (infix <–> postfix)
  • Implementing a recursive process using iteration (and a stack)

Balanced Parentheses Checker

Problem: Write a program that checks if parentheses, brackets, and braces are properly balanced in a string.

Examples:

  • \(()\) → valid
  • \(()[]{}\) → valid
  • \(([{}])\) → valid
  • \((]\) → invalid
  • \(([)]\) → invalid
  • \((((\) → invalid

Queues

Queues

  • add to the back (enqueue)
  • remove from the front (dequeue)

Queues

First In First Out                                                                                                                   

back  ┌───┬───┬───┬───┐ front
─────▶│ D │ C │ B │ A │──────▶
      └───┴───┴───┴───┘

Queues

  enqueue(E)                             
  adds to back  
       
       
back  ┌───┬───┬───┬───┬───┐  front
─────▶│ E │ D │ C │ B │ A │──────▶
      └───┴───┴───┴───┴───┘

Queues

dequeue()
removes from front


back  ┌───┬───┬───┬───┐  front    returns A
─────▶│ D │ C │ B │ A │──────▶
      └───┴───┴───┴───┘
      
            │
            ▼  after dequeue
back  ┌───┬───┬───┐  front
─────▶│ D │ C │ B │──────▶
      └───┴───┴───┘

Queues

peek()                       
returns front, no removal

 back  ┌───┬───┬───┬───┐  front   
 ─────▶│ D │ C │ B │ A │──────▶    
       └───┴───┴───┴───┘      
                  
              returns A      
              does NOT          
              remove it             

Queues

  • FIFO – First In, First Out
  • Queue basics:
    • enqueue() (adds to the end of the queue)
    • dequeue() (removes from the beginning of the queue)

Write up a generic queue interface

Solution

public interface Queue<T> {
    /**
     * Queue is First In, First Out
     * @param data is the value to be added to the end of the queue
     */
    void enqueue(T data);

    /**
     * Removes the value from the beginning of the queue and returns it
     * @return the value of type T at the beginning of the queue
     */
    T dequeue();

    /**
     * @return true if Queue is empty, false otherwise
     */
    boolean isEmpty();
}

Implementation of the Queue Interface

Queue as a linked list vs. array implementation

  • Linked List implementation – keep head and tail like we did for our first Linked List implementation
  • Array queue implementation requires some creativity because the “filled” portion of the array will tend to “move” upwards in the array with potential for lots of wasted space

Circular Array

  • Keep track of two array indices: front, rear
  • Front index is not necessarily < rear index
  • Use % operator to “wrap” around the array
    • enqueue: back = (back + 1) % capacity
    • dequeue: front = (front + 1) % capacity
  • This allows for the utilization of the entire array
  • Array is ful if number of count = array.length

Resizing?

Circular Array

   0   1   2   3   4
 ┌───┬───┬───┬───┬───┐  
 │   │   │ A │ B │   │
 └───┴───┴───┴───┴───┘
 
 front index: 2
 back index: 3
 

Circular Array

   0   1   2   3   4
 ┌───┬───┬───┬───┬───┐  
 │   │   │ A │ B │ C │
 └───┴───┴───┴───┴───┘
 
 front index: 2
 back index: 4
 

Circular Array

   0   1   2   3   4
 ┌───┬───┬───┬───┬───┐  
 │ D │   │ A │ B │ C │
 └───┴───┴───┴───┴───┘
 
 front index: 2
 back index: 0

Circular Array

   0   1   2   3   4
 ┌───┬───┬───┬───┬───┐  
 │ D │   │   │ B │ C │
 └───┴───┴───┴───┴───┘
 
 front index: 3
 back index: 0
 

Circular Array

   0   1   2   3   4
 ┌───┬───┬───┬───┬───┐  
 │ D │ E │   │ B │ C │
 └───┴───┴───┴───┴───┘
 
 front index: 3
 back index: 1