Review: the stack data structure

  • A stack data structure is like a stack of books:

Review: the stack data structure

  • The push operation will "insert"/add an item on top of the stack:

Review: the stack data structure

  • The pop operation will remove the item at the top of the stack and returns it.

  • Notice that the item removed by pop( ) is always the last item that was pushed

    The stack enforces the Last One In is the First One Out (LIFO) behavior

Review: our Stack interface definition

  • Our Stack interface definition:

       interface MyStack<E>
       {
          public boolean isEmpty(); // returns true is stack is empty
    
          public boolean isFull();  // returns true is stack is full
    
          public void push(E e);    // Pushes elem e on the stack
    
          public E pop();           // Remove the elem at the top
                                    // of the stack and return it
    
          public E peek();          // Return the elem at the top 
                                    // without removing it
       }

Review: implementing the stack using an array

  • Implementing a Stack with an array:

    1. Each array element stores one data item of the stack

    2. A stackTop index variable to record the first open position in the array

    Schematically:

  • Resizing the array:

    • Double the array size when the stack is full  (need to copy)
    • Half the array size when occupancy level < 25%

Implementing the stack using a linked list

  • The stack data structure can (also) be implemented using a linked list:

  • The first element in the linked list is the top of the stack

    The last element in the linked list is the bottom of the stack

    Schematically:

Implementing the push() and pop() operation

  • The push(item) operation is equivalent to addFirst(item):
    (I.e.: insert at the front of the list):

  • The pop() operation is equivalent to removeFirst():
    (I.e.: remove from the front of the list):

Implementing the MyStack interface with the ListStack class

  • Let's write a ListStack class that implements our MyStack interface:

    public class ListStack<T> implements MyStack<T>
    {      
        private class Node<T>
        {  
           private T item;
           private Node<T> next;
           
           public Node(T item, Node<T> next)
           {
      	  this.item = item;
      	  this.next = next;
           }
           
           public String toString(){ return "" + this.item; }
        } // End of private inner class "Node"
           
        private Node<T> first;
           
        public ListStack()  // Constructs an empty list/stack
        {  
           first = null;  // Empty list ≡ empty stack
        }  
           
        public boolean isEmpty() { ... } // returns true is stack is empty
        public boolean isFull() { ... }  // returns true is stack is full
        public void push(E e) { ... }    // Pushes elem e on the stack
        public E pop()  { ... }          // Remove and return the elem at the top
        public E peek() { ... }          // Return the elem at the top 
    }
    

Implementing the MyStack interface with the ListStack class

  • isEmpty() tests whether the list is empty and isFull() will always return false:

    public class ListStack<T> implements MyStack<T>
    {      
        private class Node<T>
        {  
           ... body omitted for brevity
        } // End of private inner class "Node"
           
        private Node<T> first;
           
        public ListStack()  // Constructs an empty list/stack
        {  
           first = null;  // Empty list ≡ empty stack
        }  
           
        public boolean isEmpty()    // returns true is stack is empty
        {
            return first == null ;
        }
    
        public boolean isFull()     // returns true is stack is full
        {
            return false;   // Because a linked list is not fixed size
        }
    
        ... other stack methods omitted for brevity
    }
    

Implementing the MyStack interface with the ListStack class

  • push(item) is the same as addFirst(item):

    public class ListStack<T> implements MyStack<T>
    {      
        private class Node<T>
        {  
           ... omitted for brevity
        } // End of private inner class "Node"
           
        private Node<T> first;
           
        public ListStack()  // Constructs an empty list/stack
        {  
           first = null;  // Empty list ≡ empty stack
        }  
    
        // push(item) --> insert at the front of the list
        public void push(T item)   
        {
           Node<T> newNode = new Node<T>(item, first);
           first = newNode;
        }
    
        ... other stack methods omitted for brevity
    }
    

Implementing the MyStack interface with the ListStack class

  • pop() is the same as removeFirst(item):

    public class ListStack<T> implements MyStack<T>
    {      
        private class Node<T>
        {  
           ... omitted for brevity
        } // End of private inner class "Node"
           
        private Node<T> first;
           
        public ListStack()  // Constructs an empty list/stack
        {  
           first = null;  // Empty list ≡ empty stack
        }  
    
        // pop() --> remove the first item and return it
        public T pop( )   
        {
           if( isEmpty() )
           {
              throw new NoSuchElementException();
           }
    
           T toReturn = first.item;   // Save return item
           first = first.next;        // Unlink the first node
           return toReturn;
        }
    
        ... other stack methods omitted for brevity
    }
    

Implementing the MyStack interface with the ListStack class

  • peek() is similar to removeFirst(item), except we do not remove the first node:

    public class ListStack<T> implements MyStack<T>
    {      
        private class Node<T>
        {  
           ... omitted for brevity
        } // End of private inner class "Node"
           
        private Node<T> first;
           
        public ListStack()  // Constructs an empty list/stack
        {  
           first = null;  // Empty list ≡ empty stack
        }  
    
        // pop() --> return the first item
        public T pop( )   
        {
           if( isEmpty() )
           {
              throw new NoSuchElementException();
           }
    
           return first.item;   // return item
        }
        ... other stack methods omitted for brevity
    }
    

SHOW: 11-linked-list/10-stack-with-list/ListStack.java

Properties of the stack implementation using a linked list

  • The push( ) and pop( ) does not have any loops

    We say that:

    • The push( ) and pop( ) runs in constant time

  • There is no need to resize the linked list !!

How to define an stack of Integer with the generic ListStack

  • We can create a stack of Integer by using Integer as parameter when defining a generic ListStack variable:

        public static void main(String[] args)
        {
            ListStack<Integer> s = new ListStack<>(5);
    
            s.push(1);
            s.push(2);
            s.push(3);
            s.push(4);
            System.out.println( s );
            System.out.println( s.pop() );
            System.out.println( s );
            System.out.println( s.pop() );
            System.out.println( s );
            System.out.println( s.pop() );
            System.out.println( s );
            System.out.println( s.pop() );
            System.out.println( s );
        }
    

DEMO: demo/11-linked-list/10-stack-with-list/Demo.java

How to define an stack of String with the generic stack

  • We can create a stack of String by using String as parameter when defining a generic ListStack variable:

        public static void main(String[] args)
        {
            ListStack<String> s = new ListStack<>(5);
    
            s.push("not");
            s.push("or");
            s.push("be");
            s.push("to");
            System.out.println( s );
            System.out.println( s.pop() );
            System.out.println( s );
            System.out.println( s.pop() );
            System.out.println( s );
            System.out.println( s.pop() );
            System.out.println( s );
            System.out.println( s.pop() );
            System.out.println( s );
        }
    

DEMO: demo/11-linked-list/10-stack-with-list/Demo2.java

Postscript: another way to implement a stack with a linked list

  • We can also implement a stack using:

    • push(item) addLast(item)

    • pop( ) removeLast( )

    However:

    • This is not preferred !!

  • Why ???

    • ???
       

Postscript: another way to implement a stack with a linked list

  • We can also implement a stack using:

    • push(item) addLast(item)

    • pop( ) removeLast( )

    However:

    • This is not preferred !!

  • Answer:

    • addLast() and removeLast() requires the use of the list traversal algorithm and will runs slower !!!