Operations on a linked list

  • The standard operations defined on a linked list include:

    1. Tests if a list is empty

    2. Get the item at the start (of the linked list)

    3. Get the item at the end (of the linked list)

    4. Insert an item at the start (of the linked list)

    5. Insert an item at the end (of the linked list)

    6. Delete the item at the start (of the linked list)

    7. Delete the item at the end (of the linked list)


    8. Get the item at position k in the linked list

    9. Remove the (first) item that contains the value key from the linked list)

A simple List interface definition

  • Important note:

    • There are many kinds of linked list that uses different linking structures

  • To unify different kinds of linked list, we define a SimpleList interface ("parent class"):

    interface SimpleList<T>  // A list that store objects of type T
    {
        public boolean isEmpty();      // Check if the list is empty
    
        public T getFirst();           // Return data in first node of list
        public T getLast();            // Return data in last  node of list
    
        public void addFirst(T item);  // Insert "item" at front of list
        public T removeFirst();        // Remove node from the front of list
    
        public void addLast(T item);   // Insert "item" at end of list
        public T removeLast();         // Remove node from the end of list
    
        public T get(int pos);         // Return item stored in node at pos
        public void remove(T key);     // Remove node containg "key"
    } 

Designing a (generic) linked list class

  • Our GenericLinkedList class must implement the SimpleList<T> interface:

    public class GenericLinkedList<T> implements SimpleList<T>
    {
       // Need variable to store a linked list...  Any ideas ?
       
       // Need a constructor to initialize the variables
    
    
        public boolean isEmpty()     ...  // Must implemet
                                          // all the methods
        public T getFirst()          ...  // declared in the
        public T getLast()	         ...  // SimpleList interface
    
        public void addFirst(T item) ...
        public T removeFirst()       ...
    
        public void addLast(T item)	 ...
        public T removeLast()        ...
    
        public T get(int pos)        ...
        public void remove(T key)    ...
    }
    

Designing a (generic) linked list class

  • Question:

    • How do you "store" a linked list ??

    • I.e.: what information does the program have on a linked list ???

  • Consider the following non-empty linked list:

    The program only has immediate access to the first node because:

    • Any idea why ?

Designing a (generic) linked list class

  • Question:

    • How do you "store" a linked list ??

    • I.e.: what information does the program have on a linked list ???

  • Consider the following non-empty linked list:

    The program only has immediate access to the first node because:

    • A list object contains only the variable first !!!

Designing a (generic) linked list class

  • Designing a class that implements SimpleList<T>:

    public class GenericLinkedList<T> implements SimpleList<T>
    {
        private Node<T> first;       // The list starts at first
    
        // Constructs an empty list
        public GenericLinkedList()    ...
    
        public boolean isEmpty()     ...  // Must implemet
                                          // all the methods
        public T getFirst()          ...  // declared in the
        public T getLast()	         ...  // SimpleList interface
    
        public void addFirst(T item) ...
        public T removeFirst()       ...
    
        public void addLast(T item)	 ...
        public T removeLast()        ...
    
        public T get(int pos)        ...
        public void remove(T key)    ...
    }
    

Designing the Node class

  • A Node of a simple list (= singly chained) contains:

    1. A data field (let's call it item)
    2. A link field (let's call it link)

  • A linked list of Integer data will have a Node class that contains an Integer:

        public class Node 
        {
           // Node instance variable is generic
           private Integer item;
           private Node    next;
    
           // Constructor for Node
           public Node(Integer item, Node next)
           {
              this.item = item;
              this.next = next;
           }
    
           public String toString(){ return "" + this.item; }
        } 
    

Designing the Node class

  • A Node of a simple list (= singly chained) contains:

    1. A data field (let's call it item)
    2. A link field (let's call it link)

  • However, a linked list of Circle objects will contain a Circle variable:

        private class Node 
        {
           // Node instance variable is generic
           public Circle  item;
           private Node    next;
    
           // Constructor for Node
           public Node(Circle  item, Node next)
           {
              this.item = item;
              this.next = next;
           }
    
           public String toString(){ return "" + this.item; }
        } 
    

Designing the Node class

  • A Node of a simple list (= singly chained) contains:

    1. A data field (let's call it item)
    2. A link field (let's call it link)

  • There, to be as flexible as possible, we use a generic (parameterized) class:

        public class Node<T> 
        {
           // Node instance variable is generic
           private  T      item;
           private Node    next;
    
           // Constructor for Node
           public Node( T      item, Node next)
           {
              this.item = item;
              this.next = next;
           }
    
           public String toString(){ return "" + this.item; }
        } 
    

Implementation note: inner classes and nested classes

  • Inner class:

    • A class that is defined inside another class is called a inner class

    Example:

       public class OuterClass
       {
           ....
    
           private class InnerClass
           {
               ....
           }
       }
    

  • We call this kind of class arrangement: nested classes

  • The purpose of nested classes is to group classes that belong together

Inner classes

  • The relationship between the inner class and it's outer class:

    • The scope of an inner class is bounded by the outer class

      I.e.:

      • the inner class does not exists independently from the outer class

    • The inner class has access to all members (including private) of its outer class

    • The outer class do not have access to the private members of an inner class

  • When to use an inner class:

    • If a class is useful only to one other class, it's more logical to:

      • Embed this class as an inner class to keep the 2 classes together...

Initial design of a (generic) linked list class

  • Because only the methods inside GenericLinkedList class will use the Node class, we will make it an inner class: of GenericLinkedList class:

    public class GenericLinkedList<T> implements SimpleList<T>
    {
        private class Node<T>  // Inner class
        {
           // Node instance variable is generic
           private T item;
           private Node<T> next;
    
           // Constructor for Node
           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;
    
        // Constructs an empty list
        public GenericLinkedList()    ...
    
        // Other methods omitted for brevity...
    }
    

A note on the constructor of the Node class

  • Notice that the constructor of the Node class initializes the next member variable using the 2nd input parameter:

    public class GenericLinkedList<T> implements SimpleList<T>
    {
        private class Node<T>  // Inner class
        {
           // Node instance variable is generic
           private T item;
           private Node<T> next;
    
           // Constructor for Node
           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;
    
        // Constructs an empty list
        public GenericLinkedList()    ...
    
        // Other methods omitted for brevity...
    }
    

The empty list

  • Recall that a linked list is stored as follows:

    Specifically:

    • The linking field in the last node contains null

  • An empty list is therefore represented as follows:

Constructor of the GenericLinkedList class:   making an empty list

  • The constructor in the GenericLinkedList class makes an empty list by setting the variable first to null:

    public class GenericLinkedList<T> implements SimpleList<T>
    {
        private class Node<T>
        {
    
            // Class content omitted for brevity...
    
        } // End of private inner class "Node"
    
    
    
        private Node<T> first;
    
        // Constructs an empty list
        public GenericLinkedList()   // <---- Constructor
        {
            first = null;    // Initialize list to empty list
        }
    
        // Other methods omitted for brevity...
    }

isEmpty(): test if a list is empty

  • The isEmpty() method returns true if the list is empty (i.e., when first == null and false otherwise:

    public class GenericLinkedList<T> implements SimpleList<T>
    {
        private class Node<T>
        {
    
            // Class content omitted for brevity...
    
        } // End of private inner class "Node"
    
    
    
        private Node<T> first;
    
        // Returns true if the list is empty
        public boolean isEmpty()    // <---- isEmpty()
        {
            return first == null;
        }
    
        // Other methods omitted for brevity...
    }

The other operations is more complex and will be discusses in the next few slides.

Summary

  • Review of the SumpleList interface:

    interface SimpleList<T>  // A list must implement these methods 
    {
        public boolean isEmpty();
    
        public T getFirst();
        public T getLast();
    
        public void addFirst(T item);
        public T removeFirst();
    
        public void addLast(T item);
        public T removeLast();
    
        public T get(int pos);
        public void remove(T key);
    } 

  • We have implement the isEmpty() method

  • We will study the addFirst() and removeFirst() methods next