Return to the lecture notes index

Lecture #9 (September, 19 2005)

Administrative Details

Event on Monday, the first test!

This test will cover the following list of material.

If we need parts of the java API then all relevant data will be given.
We can be expected to code, implement, use data structure, draw pictures of operations
This will be a pencil and bluebook exam.

Review of Interface specifications

First lets think of a class specification. A class specification is a list of the methods and constructors for a class. It is a list of all the messages that the class will send or recieve. These messages are passed via reference variables. These reference variables each have a message with it and java will check to see if this is a valid message.

The interface is similar but it has no body, no implementation code. It is just a list of method signitures with zero information about the implementation. The implementation has to be stored elsewhere. The information is still enough to serve the purpose of checking protocol. Preventing us from implementing a method on an object that it wont handle. This says nothing about how this method implements it, it just gets the type checking done, but we dont have to care about the implementation. Somewhere there needs to be the complete specification for everything in the interface. For instance if we are using a List interface reference, the LinkedList provides the implementation to use the interface. The purpose of the List interface is to be able to switch between types of lists. An example is that I want to be able to hand a static method a list and have it work no matter what type of list it is. Otherwise we would have to write several different versions of this method for each type of list and it would be more work all around.

Circularly Linked List

Here is a challenge for you, I am giving you the existing linkedlist except we are not going to have a tail. But I want to be able to add something to the end of the list in constant time. You get the head reference and the single reference between each node.

Here is a hint, I need a reference to the last node. I can't create anymore references and there can be no more nodes. So the only reference I have that is presently not used for anything is the reference of the last item in the list. This is a circular list because the last reference is going to point back to the front of the list.

Singly Linked List

head  --> node1  --> node2 --> node3

Circularly Linked List


  ______________________________
  |_>node1 --> node2 --> node3_|		
       ^
  head-|

Maybe we do something different with the head reference. If I use it as a head and I want to get to the tail I have to walk through the list. So if I use reference as a tail and I want to get to the head of the list, I walk one more.

 ________________________________
 |-> node1 --> node2 --> node3 -|
   			   ^
                     head--|

Circularly linkedlist is cool because it shows how thinking about something differently can save us time. There are costs to this method, because it only saves us one reference and costs having to move forward by one step each time we want to get to the head. It may not be a big deal but it is a deal. We dont like to propose CircularlyLinkedLists as a solution to real life situations. But it is a beautiful datastructure. Sometimes in life they can make a problem specification simpler. For instance if you were trying to do a game of duck duck goose. And you would have the player of the game give a number of children. The game could easily go aroud the circle, rather than have a special case to return to the front of the list. In the real world we no longer have to grow our own data structures, and typically the ones provided don't include circularly linked lists. Instead you would make due with a doubly linked list and add a special case to your code. Inside special code where there aren't big Libraries it might make sense to use a CircularlyLinkedList

Doubly Linked List

A doublyLinkedList is linked with both a next and a previous. We can traverse the list forward from the head to the tail, or backward from the tail to the head. I could walk until I find the node and then removing it becomes pretty simple.

  before removal:
  node1 <==> node2 <==> node3 <==>
  
  first we set node1's next to point to node3
    ________________________
    |                      v
   node1 <-- node2 <==> node3
  
 
  then we set node3's prev to point at node1
   _______________________
   |                      v
  node1     node2      node3
   ^                      |
   |______________________|

index.getPrev().setNext(index.getNext()); index.getNext().setPrev(index.getPrev());

In order to manage the data or an object we need to have a reference to it. This reference is called nondata overhead. In a singly linked list this requires twice as much nondata overhead, as opposed to just an instance of data, because we need a reference to the object and a reference to the next node. With the doubly linked list there is a third reference and it is more nondata overhead waste. Usually the objects we work with are complicated and so the overhead is small in comparison. In reality the cost comes from maintaning the extra pointer. When we dont need it it doubles the cost, but when we need it it makes the code potentially hundreds of times faster. What is the cost? On a traversal it is the same. On an insert it is 30% slower, on a remove it may be hundreds of times faster. Overall it is usually beneficial to use a DoublyLinkedList. This is different in other environments though. Sometimes LinkedLists did not hold a reference to the object but the object themselves. For instance in C where there can be a linkedlist of characters. The characters were much smaller in size when compared to the references on either side. So the overhead of a doubly linked list would have been very large by comparison.

Alright onto the SubEthaEdit and some coding

Our goal in life is to convert our singly linkedlist file into a doubly linkedlist. Here is the uncompleted file: DoublyLinkedList.java

class DoublyLinkedList{
// change appropriate LinkedList to DoublyLinkedList
// for example  the LinkedListIterator now has
 public class LinkedListIterator implements Iterator{

   private DoublyLinkedList ll;

 }

}

Lets come down and play with our Node Class first. Our node has an item and a next now it will have a node prev


private class Node{

  private Node prev;  // new reference variable
  private Object item;
  private Node next;

// then we have to add prev to the constructors
   
  public Node (Object item){
  this.prev = null;
  this.item = item;
  this.next = null;
  }


  public Node ( Node prev, Object item, Node next) {
   this.prev = prev;
   this.item = item;
   this. next = next;
  }
// we have a getNext() we need a getPrev()

  public Node getPrev(){
    return prev;

  }

// we have a setNext() we need a setPrev()

  public void setPrev( Node prev){
   this.prev = prev;
  }

}

At this point the node class is completed.

Between now and Wednesday we are going to go through and figure out what we need to do to convert this from a SinglyLinkedList to a DoublyLinkedList. We will convert it Wednesday in class.