Review: the queue data structure

  • A queue data structure is like a queue of people:

  • The enqueue( ) operation will "insert"/add an item on tail of the queue:

Review: the queue data structure

  • A queue data structure is like a queue of people:

  • Dequeue( ) will remove the item at the head of the queue and returns it.

Review: our Queue interface definition

  • Our MyQueue interface definition:

       interface MyQueue<E>
       {
          boolean isEmpty(); // returns true is queue is empty
    
          boolean isFull();  // returns true is queue is full
    
          void enqueue(E e); // Insert elem e at the back of the queue
    
          E dequeue();       // Remove the elem at the front
                             // of the queue and return it
    
          E peek();          // Return the elem at the front
                             // without removing it
       }

Review: implementing a queue using a circular (array) buffer data structure

  • The circular buffer data structure consists of an array with 2 "pointers" or indices:

    • Read pointer = the index of the read position in array
    • Write pointer = the index of the write position in array

    Schematically:

Implementing the queue using a linked list

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

  • The first element in the linked list is the front of the queue

    The last element in the linked list is the back of the queue

    Schematically:

Implementing the enqueue() and dequeue() operations

  • The enqueue(item) operation is equivalent to addLast(item):
    (I.e.: insert at the end of the list):

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

Implementing the MyQueue interface with the ListQueue class

  • Let's write a ListQueue class that implements our MyQueue interface:

    public class ListQueue<T> implements MyQueue<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 ListQueue()  // Constructs an empty list/queue
        {  
           first = null;  // Empty list ≡ empty queue
        }  
           
        public boolean isEmpty() { ... } // returns true is queue is empty
        public boolean isFull() { ... }  // returns true is queue is full
        public void enqueue(E e) { ... } // Insert elem e into the queue
        public E dequeue()  { ... }      // Remove and return elem at front
        public E peek() { ... }          // Return the elem at the front 
    }
    

Implementing the MyQueue interface with the ListQueue class

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

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

Implementing the MyQueue interface with the ListQueue class

  • enqueue(item) is the same as addLast(item):

    public class ListQueue<T> implements MyQueue<T>
    {      
        private class Node<T>
        {  
           ... omitted for brevity
        } // End of private inner class "Node"
           
        private Node<T> first;
           
        // enqueue(item) --> insert at the end of the list
        public void enqueue(T item)   
        {
            if ( isEmpty() )
            {
                first = new Node<T>(item,null);
            }
            else
            {
                Node<T> current = first;
                while( current.next != null )   // Find the last node
                {
                   current = current.next;
                }
                current.next = new Node<T>(item,null); // Link behind the last node
             }
         }
        ... other queue methods omitted for brevity
    }
    

Implementing the MyQueue interface with the ListQueue class

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

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

Implementing the MyQueue interface with the ListQueue class

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

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

SHOW: demo/11-linked-list/11-queue-with-list/ListQueue.java

How to define an queue of Integer with the generic ListQueue

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

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

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

How to define an queue of String with the generic queue

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

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

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

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

  • We can also implement a queue using:

    • enqueue(item) addFirst(item)

    • dequeue( ) removeLast( )