# List

We will begin our study of data structures with lists. These are structures whose elements are in a linear order.

```public interface List extends Container {
public Iterator elements(); // ignore for now!
// post: returns an iterator allowing
//   ordered traversal of elements in list

public int size();          // from Container
// post: returns number of elements in list

public boolean isEmpty();   // from Container
// post: returns true iff list has no elements

public void clear();        // from Container
// post: empties list

// post: value is added to beginning of list

// post: value is added to end of list

public Object peek();
// pre: list is not empty
// post: returns first value in list

public Object tailPeek();
// pre: list is not empty
// post: returns last value in list

// pre: list is not empty
// post: removes first value from the list

public Object removeFromTail();
// pre: list is not empty
// post: removes the last value from the list

public boolean contains(Object value);
// post: returns true iff list contains an object equal
//  to value

public Object remove(Object value);
// post: removes and returns element equal to value
//       otherwise returns null
}
```

We can imagine other useful operations on lists, such as return nth element, etc., but we'll stick with this simple specification for now.

The text has a simple example of reading in successive lines from a text and adding each line to the end of a list if it doesn't duplicate an element already in the list. This is easily handled with the operations provided.

## Vector Implementation

Suppose we decided to implement List using a vector:

```public class VectList implements List
{
protected Vector listElts;

public VectList()
{
listElts = new Vector();
}
....
}
```

How expensive would each of the operations be (worst case) if the VectList contains n elements?

Some are easy. Following are O(1). Why?

```    size(), isEmpty(), peek(), tailPeek(),  removeFromTail()

```
Others take more thought:
```    clear();                    // O(n) currently, because reset all slots
// to null, but could be O(1)
removeFromHead();           //O(n) - must move contents
contains(Object value);     //O(n) - must search
remove(Object value);       //O(n) - must search & move contents

```
The last is the trickiest:
```    addToTail(Object value);

```
If the vector holding the values is large enough, then it is clearly O(1), but if needs to increase in size then O(n). If use the doubling strategy then saw this is O(1) on average, but O(n) on average if increase by fixed amount.

All of the other operations have the same "O" complexity in the average case as for the best case.

Linked list is composed of series of nodes, each of which has a reference to the next.

First provide SinglyLinkedListElement class representing the nodes:

```class SinglyLinkedListElement {
// these public fields protected by private class

Object data;        // value stored in this element
// ref to next element

// constructors

// post: constructs a new element with value v,
//       followed by next
{
data = v;
nextElement= next;
}

// post: constructs a new element of a list with value v
//          but with nothing attached.
{
this(v,null);
}

// post: returns reference to next value in list
{
return nextElement;
}

// post: sets reference to new next value
{
nextElement = next;
}

public Object value()
// post: returns value associated with this element
{
return data;
}

public void setValue(Object value)
// post: sets value associated with this element
{
data = value;
}

public String toString()
// post: returns string representation of element
{
}
}
```

Bit like an association, but association to itself - i.e., it is recursive!

The actual linked list implementation is pretty straightforward, but to understand the code you MUST draw pictures to see what is happening!

```public class SinglyLinkedList implements List {
protected int count;                    // list size

// post: generates an empty list.
{
count = 0;
}

// post: adds value to beginning of list.
{
}

// post: add value to beginning of list.
{
// note the order that things happen:
// head is parameter, then assigned!!!
count++;
}

// pre: list is not empty
// post: removes and returns value from beginning of list
{
count--;
return temp.value;
}

// post: adds value to end of list
{
// location for the new value
{
// pointer to possible tail
while (finger.next() != null)
finger = finger.next();
finger.setNext(temp);
}
else
count++;
}

public Object removeFromTail()
// pre: list is not empty
// post: last value in list is returned
{
// keep two ptrs w/ previous one elt behind finger

Assert.pre(head != null,"List is not empty.");
while (finger.next() != null) // find end of list
{
previous = finger;
finger = finger.next();
}
// finger is null, or points to end of list
if (previous == null)   // list had 1 or 0 elements
else        // pointer to last element reset to null.
previous.setNext(null);
}
count--;
return finger.value();
}

public Object peek()
...

public Object tailPeek()
// find end of list as in removeFromTail

public boolean contains(Object value)
// pre: value is not null
// post: returns true iff value is found in list.
{
while (finger != null && !finger.value().equals(value))
finger = finger.next();
return finger != null;
}

public Object remove(Object value)
// pre: value is not null
// post: removes 1st element with matching value, if any.
{
while (finger != null && !finger.value().equals(value))
{
previous = finger;
finger = finger.next();
}
// finger points to target value
if (finger != null) {
// we found the element to remove
if (previous == null) // it is first
else              // it's not first
previous.setNext(finger.next());
count--;
return finger.value();
}
// didn't find it, return null
return null;
}

public int size()
// post: returns the number of elements in list
{
return count;
}

public boolean isEmpty()
// post: returns true iff the list is empty
{
return size() == 0;
}

public void clear()
// post: removes all elements from the list
{