CS62 - Fall 2020 - Class 8
Example code in this lecture
LinkedList
Lecture notes
admin
- quiz today
- Darwin due on Tuesday
- Remote support
The general ArrayList class implements the List interface (
http://docs.oracle.com/javase/7/docs/api/java/util/List.html
)
- Which of the following methods are performed quickly by the ArrayList class (quickly being sub-linear)? Slowly?
- get
- set the value of an existing element
- add to the end
- contains/indexOf
- add at an index
- remove an element
- size
- Quick:
- get
- set
- add to the end (like we saw last time... amortized)
- size
- Slow:
- adding an element at a particular index
- have to shift everything after towards the end
- removing an element
- have to remove and shift everything after towards the front
- contains
- have to iterate over every item
No free lunch!
- there's no one best data structure
- to make certain operations fast we often have to compromise and make other operations slower
- depending on what operations are important, one data structure may be more appropriate than another
- we're going to start looking at different data structures that are good at different things
Linked lists
- linked lists are a *recursive* data structure
- the data structure is built out of nodes
- a node stores both a data item as well as a reference to another node
- draw a picture and compare and contrast a picture of an array
- how could we do this using a class?
- look at the Node class in
LinkedList code
- we'll use generics again to make the class general purpose
- two things that we keep track of (with private instance variables)
- private E data: the data that we're actually storing in the node
- private Node next: a link to the next node in our linked list
- we have methods that allow us to access and manipulate the data within the node
- as well as methods that allow us to traverse and manipulate the links
- We want to build a linked list data structure that supports similar operations to ArrayList (i.e., the List interface). How would we do it?
- we'll just store a link the head of the linked list
- all of our operations will start at the head and then modify/traverse the list appropriately
- look at the LinkedList class in the
LinkedList code
- only keep track of a single node, the head of the list
- Look at the two addFirst methods in
LinkedList code
- addFirst
- create the new node
- set the next value of that new node to head
- set head to be the new node
- addFirst2
- does the same things, but utilizing the Node constructor
- when we evaluate the right hand side head gets passed as the next parameter to the Node
- we then just store this new node directory as the head
- how would we remove the first element (assuming that there is at least one element)?
- look at removeFirst in
LinkedList code
- save the value of head so we can return it
- set head to be head.next()
- return the value of the original head
iterating through linked lists
- how can we iterate through all of the values in a linked list?
- how do we know were the end of the list is?
- it will be a node whose next value is null
- make a variable (it's often called "finger" and then move it down the list until we fall off of the end)
Node finger = head;
while (finger != null ) {
// do something with the current node, finger
finger = finger.next();
}
- do it recursively:
void iterate(Node current){
if( current == null ){
return null;
} else {
// do something with current
iterate(current.next());
}
}
write a method contains(E value). Returns true if the linked list has that value (based on .equals) and false otherwise
- look at contains in
LinkedList code
- start at the head and traverse through the nodes
- key: check if we've seen the node
- stop when we either find it or we run off the end
- at the end, see if we either found it or if we fell off the end of the list
- look at recursiveContains in
LinkedList code
- recursive data structures are often conducive to recursive method
- start at the head
- two base cases: we're either null or we've found it
- if neither of this, look at the next eleement
Which of these methods are fast/slow for singly linked lists?
- add to the end (slow)
- add to the front (fast)
- contains (slow)
- get (slow)
- insert at an index
- remove an element
- set the value of an existing element
- size
What does the singly linked list buy us?
- add and remove at the front of the list in constant time!
- what is the downside (no free lunch!)?
- get and set are now linear time operations