Universidad Carlos III de Madrid

Ingeniería de Telecomunicación

Enero-Mayo 2010 / January-May 2010

Queues Exercises

Lab Section1.  Work in Lab

TimeTOTAL: 90 min

Exercise Section1.1.  Implementing stacks with linked lists

Time50 min

Objective

The resolution of this exercise expects that the student learns to implement a stack using linked lists as data structure.

Section 1

Implement an stack using a linked list as data structure. The stack must allow to store any object type and you must implement at least the following methods:

- Insert an object in the stack (push).

- Retrieve an object from the stack (pop).

- Retrieve the object from the top of the stack, without extracting.

- Find out if there is any object in the stack.

- Return the number of objects in the stack.

Design the class deciding methods name, their parameters and return value. (Tip: Create a Node class which stores the stack values).

Nodes in a linked list, like the one you are going to use in this exercise, are linked to each other using the next attribute of Node class. On the other hand, every node uses the elem attribute to point to the object that it has to store in it.

Section 2

Implement a test class so that it reads lines from a file and prints them to console in reverse order. For example, if the file has four lines "A", "B", "C" and "D", it should print lines "D", "C", "B", "A".

Exercise Section1.2.  Implementation of a queue with linked lists

Time40 min

Objective

In this exercise, you will have to implement a linked list - based queue. Then, further methods will be added so that new functionalities can be achieved in order to reinforce concepts about lists.

A queue is a data structure where insertion and deletion of elements is made following the FIFO (First In First Out) principle. That is, the first element that is extracted from the queue is also the first element that is introduced into the queue.

The queue is represented as a linked list. One of the ends can be considered as the top of the queue (that is, the node referenced as top). The other end represents the last position of the queue (the node whose next node is null). Therefore, extracting an element out the the queue consists on returning the top's object and unlinking it. On the other hand, insertion of a new object consists of locating the last node and linking it to the new object's node. To avoid crossing the whole list to find the last node, it is recommended to have an attribute that points to the last node of the queue. Thik of this linked list as a queue at market. The grocer knows who goes first and who is the last one. Every customer knows who follows him.

Nodes in a linked list, like the one you are going to use in this exercise, are linked to each other using the next attribute of Node class. On the other hand, every node uses the info attribute to point to the object that it has to store in it.

As it is shown, LinkedQueue class mantains two attributes, a top that points to the top of the queue and where elements are extracted from. The other one is the tail attribute, where elements are introduced into the queue. The FIFO's principle is carried out in this way.

  1. We are modelling the reception and process of purchase orders in a company. Let's suppose that the company makes only one product. The company receives orders from different customers. Every order has two characteristics: customer and units of product. The orders are processed by order (FIFO). Below, you can download the definition of (class Order). Order.java

    public class Order {
            private String customer;
    	private int qtty;
    		public Order(int qtty, String customer) {
    			this.customer=customer;
    			this.qtty = qtty;
    		}
    		public void print (){
    			System.out.println("     Customer: " + this.getCustomer());
    			System.out.println("     Quantity: " + this.getQtty());
    			System.out.println("     ------------");
    		}
    		public int getQtty(){
    			return this.qtty;
    		}
    		public String getCustomer(){
    			return this.customer;
    		}
    }
    
    	  

    Implement the Queue class that implements the following interface:

    public interface QueueInterface {
    
        // returns the number of elements in Queue
        public int size();                   
    
        // verifies if the Queue is empty. true if empty | false if not empty.
        public boolean isEmpty();
    
        // returns the first element in Queue. The element IS NOT REMOVED from Queue. Returns null if empty.
        public Object front();
    
        // adds a new element to the Queue.
        public void enqueue(Object info);
     
        // returns the first element in Queue. The element IS REMOVED from Queue. Returns null if empty.
        public Object dequeue();
    } 
    
    	

    To do it, implement also the Node class that represents each node in the linked queue. Every node will have 2 references: one to the next node in the list, and one to the element attached to that node.

    Implement a TestQueue class with a main to test the code.

    To better test the code, add a new method printInfo() to the Queue class. This method should print the size of the queue and should go from first element to last one and present the data contained inside each order, by using the print() method from Order class. That is, it should present something similar to:

    ********* QUEUE DUMP *********                 
       Size: 4                                     
       ** Element 1                                
         Customer: cust1                           
         Quantity: 20                              
         ------------                              
       ** Element 2                                
         Customer: cust2                           
         Quantity: 30                              
         ------------                              
       ** Element 3                                
         Customer: cust3                           
         Quantity: 40                              
         ------------                              
       ** Element 4                                
         Customer: cust3                           
         Quantity: 50                              
         ------------                              
    ******************************                 
    

    The program has to walk the linked list in order to show its elements. It begins with the first node, then the second node is reached through the next reference in the first one, then the third node, and so on until the end of the list is reached. The code for that should be something like:

    Node node = top;
    while (node != null) {
      // print here the information of the node
      (...)
      node = node.getNext();
    }
    

    In the main method, create a new queue and, at least, 3 new orders. Add them to the queue and test the methods front and dequeue. To better check the effect, after every insertion or deletion, use the printInfo method.

  2. Once we feel comfortable with a very simple queue, we will make it a little bit complex: Implement a method to obtain the n-th element, without deleting it. It must return null if the position is not valid. public Object getNth(int pos) To test it, try to add 4 elements and obtain the third one.

Homework Section2.  Homework

Time110 min
Time60 min

Objective

To study in depth the use of linked list data structures.

Exercise

The List class represents a linear collection of data organized in a linked list. This list shows the peculiarity of storing a reference to a particular node in the list, which is pointed by the reference currentPosition and on which data insertion and extraction operations are performed.

The reference currentPosition must be able to move forwards and backwards through the list, position by position. It is therefore appropriate for the list to be double linked, i.e. each node store a reference not only to the following node in the list, but also to the node that precedes it. The following figure illustrates the structure of the list with an example:

The basic operations this list should allow are:

  1. Move the reference position forwards: the reference is moving forwards as many positions as indicated. If the list is empty or the number of positions to move forwards is not greater than zero, nothing is done. If it is required to move it forwards more positions than number of nodes from the current position up until the end of the list, advance currentPosition only until the last node. If currentPosition points to null before proceeding, it is first placed pointing to the first node of the list, and then moved forwards the specified number of positions minus one (for example, if it is required to move 5 positions forwards and currentPosition points initially to null, then currentPosition is first placed pointing to the first node, and then moved 4 positions from this first one).

  2. Move the currentPosition reference backwards: the reference currentPosition must go backwards as many positions as indicated. If the list is empty or the number of positions to move backwards is not greater than zero, nothing is done. If it is required to move backwards more positions than number of nodes from the current position up until the first node of the list, the reference will remain in this first node.

  3. Insert new data in the list: a new node is inserted to save this data, immediately following currentPosition, i.e. the new node will follow the node currently referenced by currentPosition. When currentPosition is null, the new node is inserted into the top of the list. After the insertion, currentPosition must point to the new node inserted.

  4. Extracting data from the list: return the data pointed by currentPosition, delete the node, and moves currentPosition to the next node (currentPosition will point to null if there is no next node). If currentPosition is pointing to null, nothing is extracted and null is returned.

Program the Node class, the List class and the following methods of the List class:

  1. public void moveForwards(int numPositions) {...}

  2. public void moveBackwards(int numPositions) {...}

  3. public void insert(Object data) {...}

  4. public Object extract() {...}

Time30 min

Objective

To learn how to work with Deques.

Exercise

A Deque, is a linear data structure that permits to insert and to remove elements on both sides. To build it, we will be based on the use of a Double Linked List (DLL) on which we will implement the corresponding methods to achieve such behaviour.

A Deque's behaviour can be achieved by the implementation of the following interface that shows its main methods:

/** 
* Interface for a Deque. 
*  
* @author DIT-UC3M 
*  
*/  
   public interface Dqueue {  
   
      void insertFirst(Object obj);  
 
      void insertLast(Object obj);  
 
      Object removeFirst();  
 
      Object removeLast();  

      int size();  
   }

To implement a Deque by using a DLL, perform the following tasks:

  1. Program the DNode class which represents the node of a Double Linked List (DLL). Such node will contain both prev and next references to the previous and next node of the current one, as well as an Object reference to the data to be stored.

  2. Declare the DLDqueue class that will implement a Deque based on a DLL. In order to do this, it must implement the Dqueue interface that has been previously mentioned.

  3. Add the head and tail attributes that represents the nodes at both ends of the DLL and the integer attribute size that permits to store the size of it.

  4. Program the constructor of the DLDqueue class that initializes the head and tail references to an emtpy DLL node and set the size to 0.

  5. Program the following methods of the Dqueue's interface:

    • public void insertFirst(Object obj)

      This method inserts an object at the beginnig of the DLL.

    • public void insertLast(Object obj)

      This method inserts an object at the end of the DLL.

    • public Object removeFirst()

      This method extracts an object from the beginning of the DLL and removes it from the list. If such object does not exist, the method returns null.

    • public Object removeLast()

      This method extracts an object from the end of the DLL and removes it from the list. If such object does not exist, the method returns null.

    • public int size()

      This method returns the size of the DLL list.

  6. Finally, implement the public String toString() method that permits to print the content of the Deque on console according the next format (the shown values are examples):

    head [ 1-2-3-4-5 ] tail

IMPORTANT NOTE!!

In this exercise, we have practice with the design and implementation of a Deque. However, in the Java API there are also several classes that implement such data structures. A Deque is defined by the following interface: Interface Deque. There are also two possible class implemntations of it, one that is based on arrays (ArrayDeque) and another one based on linked lists (LinkedList).

Time20 min

Objective

To learn how to make a Deque to behave as a Stack or a Queue.

Exercise

In this exercise, we will take advantage of the flexiblity of a Deque to make it behave as if it was a Stack or a Queue. For this, we will force the class using the Deque to implement the corresponding interface that is shown next:

  • Stack interface:

    /** 
    * Interface for a Stack. 
    *  
    * @author DIT-UC3M 
    *  
    */  
       public interface Stack {  
       
          void push(Object obj);  
      
          Object pop();  
    
          int size();  
       }
    
  • Queue interface:

    /** 
    * Interface for a Queue. 
    *  
    * @author DIT-UC3M 
    *  
    */  
       public interface Queue {  
      
          public void enqueue(Object obj); 
    
         public Object dequeue();  
    
          int size();  
       }
    
    

Next, let's use a Deque to implement both a Stack or a Queue. In order to do this, perform the following tasks:

  • To implement a Stack by a Deque:

    1. Declare the DQStack class that should behave like a Stack. In order to do this, it should implement the Stack interface that has been previously mentioned.

    2. Add a data attribute of DLDqueue type which constitutes the list where stack's data will be stored.

    3. Program the DQStack class constructor that should initialize the data attribute creating an instance of a DLDqueue class.

    4. Program the following methods of the Stack's inteface:

      • public void push(Object obj)

        This method inserts an object at the beginning of the DLDqueue.

      • public Object pop()

        This method extracts an object from the beginning of the DLDqueue and it removes it from the list. If such object does not exist, the method returns null.

      • public int size()

        This method returns the size of the DLDqueue.

    5. Implemet the main method to test the Stack. It must instantiate a DQStack object, pushing and popping several data while it prints on console the content and the size of the stack.

  • To implement a Queue by a DLDqueue:

    1. Declare the DQQueue class that should behave like a Queue. In order to do this, it should implement the Queue interface that has been previously mentioned.

    2. Add a data attribute of DLDqueue type which constitutes the list where queue's data will be stored.

    3. Program the DQQueue class constructor that should initialize the data attribute creating an instance of a DLDqueue class.

    4. Program the following methods of the Queue's inteface:

      • public void enqueue(Object obj)

        This method inserts an object at the beginning of the DLDqueue.

      • public Object dequeue()

        This method extracts an object from the end of the DLDqueue and it removes it from the list. If such object does not exist, the method returns null.

      • public int size()

        This method returns the size of the DLDqueue.

    5. Finally, implement the main method to test the Queue. It must instantiate a DQQueue object, queueing and enqueueing several data while it prints on console the content and the size of the queue.