### Improving the implementation using a tail reference

• Inefficiency in the queue implementation using a list

• Dequeue is extremely fast:

 ``` public double dequeue( ) throws Exception { if ( head == null ) throw new Exception("Remove from empty list"); double r; r = head.value; // Save return value head = head.next; // Delete elem at head return r; // Return the value saved } ```

Running time of dequeue():

 O(1) (i.e., a constant number of statements

• However, the enqueue() operation is slow:

 ``` public void enqueue( double x ) { Node e; e = new Node( x ); // Make node with value x if ( head == null ) { /* ------------------------------ Insert e into an empty list ------------------------------ */ head = e; // e is the first elem. e.next = null; // Mark e as the last Node. } else { /* ------------------------------ Insert e into a non-empty list ------------------------------ */ // Find the last Node in the list Node ptr; ptr = head; while ( ptr.next != null ) ptr = ptr.next; // ptr NOW points to the last Node in list // Add e AFTER last Node ptr.next = e; // Make the last node point to e e.next = null; // Mark e as the last Node } } ```

Running time of enqueue():

 O(n) (because it needs to traverse the entire list of n nodes)

• Improving the performance of enqueue

• Cause of the inefficiency:

 Enqueue() must first find the last element in the list

• Solution:

• Add another variable in the list class that keep track of the last node in the list:

 ``` public class ListQueue implements Queue { ... public Node head; // head points to first Node of the list // **** Access SHOULD be set to private **** public Node tail; // tail points to **LAST** Node of the list ... } ```

• How the variable tail can eliminate the search for the last node:

• Warning: there is no free lunch !!!

• Warning:

 When you added more variables to a program, we must maintain the information stored in the new variables !!!

• How to maintain information stored in variables:

 Find out when the information in the variable change Write code to update the information accordingly

• Maintaing the tail variable:

• The last node can change when we:

 Insert into the list (because we insert at the tail of the list) Delete the last node from the list

• Specifically:

 When we insert a new node at the tail, we must update the tail variable to point to the new last node !!! When we delete the last node from the list, we set tail to null

• Improved implementation of the queue with a list

• Java code:

 ``` public class ListQueue implements Queue { /* ========================================== Node "inner class" ========================================== */ public class Node { double value; Node next; public Node( double x ) { value = x; next = null; } public String toString() { return "" + value; } } public Node head; // head points to first Node of the list // **** Access SHOULD be set to private **** public Node tail; // tail points to **LAST** Node of the list // Constructor public ListQueue() { head = null; // Make an empty list tail = null; // You must maintain tail ALSO !!! } /* ==================================================== enqueue(x ): store value x into the list - at tail ==================================================== */ public void enqueue( double x ) { Node e; e = new Node( x ); // Make node with value x if ( head == null ) { /* ------------------------------ Insert e into an empty list ------------------------------ */ head = e; // e is the first node. tail = e; // e is ALSO the last node. e.next = null; // Mark e as the last Node. } else { /* ------------------------------ Insert e into a non-empty list ------------------------------ */ Node ptr; ptr = tail; // NO NEED to "find" the last Node !!! // ptr points to the last Node in list // Add e AFTER last Node ptr.next = e; // Make the last node point to e e.next = null; // Mark e as the last Node tail = e; // Update tail !!! (e is the last node !) } } /* ==================================================== dequeue(): delete the head node in list Return the value that was stored in this elemenet ==================================================== */ public double dequeue( ) throws Exception { if ( head == null ) throw new Exception("Remove from empty list"); double r; r = head.value; // Save return value head = head.next; // Delete elem at head /* ==================================== Make tail == null if list is empty ==================================== */ if ( head == null ) { tail = null; // You must maintain "last" !!! } return r; // Return the value saved } } ```

• Test program:

 ``` public static void main( String[] args ) throws Exception { Queue myQ = new ListQueue(); double x; myQ.enqueue(1.0); System.out.println("enqueue(1.0): " + "myQ = " + myQ); myQ.enqueue(2.0); System.out.println("enqueue(2.0): " + "myQ = " + myQ); myQ.enqueue(3.0); System.out.println("enqueue(3.0): " + "myQ = " + myQ); System.out.println("\nBefore dequeue:"); System.out.println("myQ = " + myQ); x = myQ.dequeue(); System.out.println("x = " + x + ", myQ = " + myQ); x = myQ.dequeue(); System.out.println("x = " + x + ", myQ = " + myQ); x = myQ.dequeue(); System.out.println("x = " + x + ", myQ = " + myQ); } ```

Output:

 ``` enqueue(1.0): myQ = [1.0] enqueue(2.0): myQ = [1.0 , 2.0] enqueue(3.0): myQ = [1.0 , 2.0 , 3.0] Before dequeue: myQ = [1.0 , 2.0 , 3.0] x = 1.0, myQ = [2.0 , 3.0] x = 2.0, myQ = [3.0] x = 3.0, myQ = [] ```

• Example Program: (Demo above code)

How to run the program:

 Right click on link and save in a scratch directory To compile:   javac testProg.java To run:          java testProg