CS 46B - Lecture 16

Cover page image

Pre-class reading

Implementing Linked Lists

Adding at Head

public void addFirst(Object element)
{
   Node newNode = new Node(); 
   newNode.data = element;
   newNode.next = first; 
   first = newNode; 
}

Lecture 16 Clicker Question 1

It is very easy to make mistakes when updating the links. Suppose you had forgotten the last line in the method of the preceding slide:

public void addFirst(Object element)
{
   Node newNode = new Node(); 
   newNode.data = element;
   newNode.next = first; 
   first = newNode; 
}

What would happen?

  1. addFirst would not compile.
  2. A NullPointerException would happen whenever addFirst is called.
  3. addFirst would have no effect on the contents of the linked list.
  4. addFirst would add an element after the first node, not before it.

Lecture 16 Paper Question 1

It's your turn. Implement a method addSecond that adds an element after the first node, not before it. You may assume that the linked list has at least one element.

Make a sketch similar to the one in the book for addFirst.

Write your name and student ID on your sheet. When prompted, hand it to the front.

Lecture 16 Clicker Question 2

Now implement what you just wrote in this program.

What happened?

  1. It printed Diana Harry Romeo Tom
  2. It printed Harry Diana Romeo Tom
  3. It printed "... corrupted"
  4. Something else happened

Removing at Head

public class LinkedList
{
   . . .
   public Object removeFirst()
   {
      if (first == null) { throw new NoSuchElementException(); }
      Object element = first.data;
      first = first.next; 
      return element;
   }
   . . .
}

Iterator Class

Iterator Class

  • It is an error to call remove twice in a row, without a call to next in between
    String next = iter.next();
    iter.remove(); // ok
    iter.remove(); // NOT ok
    
  • Also, set must immediately follow next:
    while (iter.hasNext())
    {
       String next = iter.next();
       if (we do not like next)
          iter.set(something better);
    }
  • class LinkedListIterator implements ListIterator
    {
       private Node position;
       private Node previous;
       private boolean isAfterNext; 
       ...
    }
  • previous is needed for removal
  • Advancing Iterator

    public Object next()
    {
       if (!hasNext()) { throw new NoSuchElementException(); }
       previous = position; // Remember for remove
       isAfterNext = true;
       if (position == null)
       {
          position = first;
       }
       else
       {
          position = position.next;
       }
       return position.data;
    }
    

    hasNext

    public boolean hasNext()
    {
       if (position == null)
       {
          return first != null;
       }
       else
       {
          return position.next != null;
       }
    }
    

    remove

    public void remove()
    {
       if (!isAfterNext) { throw new IllegalStateException(); }
       if (position == first)
       {
          removeFirst();
       }
       else
       {
          previous.next = position.next;  
       }
       position = previous;  
       isAfterNext = false;
    }

    Lecture 16 Clicker Question 3

    Suppose we removed the lines

       if (!isAfterNext) { throw new IllegalStateException(); }

    and

       isAfterNext = false;

    from the remove method. What would happen if one called remove twice in a row?

    1. The preceding element would be always be removed
    2. The preceding element would only be removed if it was the first one
    3. The second call to remove would have no effect
    4. An exception would occur

    add

    public void add(Object element)
    {
       if (position == null)
       {
          addFirst(element);
          position = first;
       }
       else // see Paper Question 2
       {
          Node newNode = new Node();
          newNode.data = element;
          newNode.next = position.next;  
          position.next = newNode;  
          position = newNode;  
       }
       isAfterNext = false;  
    }
    

    Lecture 16 Paper Question 2

    I've done a lot of drawing for you. Now it's your turn. You draw up the second scenario of the add method, as nicely as you can.

    Write your name and student ID on your sheet. When prompted, hand it to the front.

    Efficiency of Singly-Linked List Operations

    Lecture 16 Clicker Question 4

    Actually, the table from the last slide isn't true for the implementation that we just studied. Which of them is false?

    1. Add/remove at iterator position: O(1)
    2. Add/remove first element: O(1)
    3. Add last element: O(1)
    4. Remove last element: O(n)

    Lecture 16 Clicker Question 5

    Ok, so let's add a tail reference.

    public class LinkedList
    {
       private Node first;
       private Node last;
       ...
    }
    

    Now we need to update it in all methods that mutate the list. Here is ListIterator.remove:

    public void remove()
    {
       if (!isAfterNext) { throw new IllegalStateException(); }
       if (position == first)
       {
          removeFirst();
       }
       else
       {
          previous.next = position.next;  
       }
       if (___) ___; 
       position = previous;  
       isAfterNext = false;
    }

    What should be filled in for the two ___?

    1. position == last / position = previous;
    2. position == null / last = previous;
    3. position == last / last = previous;
    4. previous == last / last = position;