Upload
rolf-parrish
View
220
Download
3
Embed Size (px)
Citation preview
198
Common Cartoon Mistakes
hellipvery relevant to Doodle Jump
298
Cartoon Mistakes (13)
Composite shape class extending JPanelo Composite shape does not need to be a JPanelo Instead it should be a group of Shapes that is contained both
graphically and logically by the DrawingPanel
Composite shape class extending Shapeo This doesnrsquot provide any of the functionality that you need for a
composite shapeo Easier to not extend anything and write the necessary methods
yourself
398
Cartoon Mistakes (23)
Using containment instead of inheritance incorrectly For example we donrsquot want our DrawingPanel to contain a JPanel
We want our DrawingPanel to be a JPanel with added functionality
Putting an int into JLabelrsquos setText method JLabelrsquos setText method can only take in Strings If you want it to display an int you must convert the int to a
String passing in your int to the static method IntegertoString (see Javadocs for more info)
498
Cartoon Mistakes (33)
Making a separate JPanel for every different Shape in DrawingPanel This makes it difficult to manage all the components of your cartoon This kind of structure will make it hard to add on to your program if you
ever wanted to make edits Structuring your program so that it is extensible and can be scaled easily is very important in the real world
598
Continuation from last time
698
An Aside Java Autoboxingbull What do you do when you want to store an int
(or some other primitive) in an ArrayList in Java
bull You cannot use a generic with a primitive type So you can use the built-in class which is equivalent to that primitiveo int -gt Integero double -gt Double
bull If you use a built-in class that is equivalent to a primitive as a generic then with methods which take the generic type as a parameter you can pass in both an object of the built-in class or a primitive
bull Additionally the return values of methods which return a generic type can be stored in a variable of either the built-in class type or the primitive type
bull This is called Autoboxing
int x = 0ArrayListltIntegergt list = new ArrayListltIntegergt()listadd(x)int y = listget(0)
798
Merge Sort Summary
bull There are 2 main parts to this algorithmo First recursively divide list in half until
base case of one element is reached (one element is base case because a single element is always sorted)
o Then at each recursive level take each of the sorted sub-arrays and merge them together to make a sorted list
o Due to the recursion you have at the end a full sorted list
898
Merge Sort Animation
bull Unlike prior examples this animation sorts based on numbers directly not using height of the bar to visualize their value
998
Updated Merge Sort Codepublic ArrayListltIntegergt mergeSort(ArrayListltIntegergt input) ArrayListltIntegergt sortedList = new ArrayListltIntegergt() if (inputsize()lt2) for (int el input) sortedListadd(el) return sortedList
ArrayListltIntegergt left = new ArrayListltIntegergt() ArrayListltIntegergt right = new ArrayListltIntegergt() int middle = inputsize()2 for (int i =0 iltinputsize() i++) if (iltmiddle) leftadd(inputget(i)) else rightadd(inputget(i))
ArrayListltIntegergt sortedLeft = thismergeSort(left) ArrayListltIntegergt sortedRight = thismergeSort(right) sortedList = thismerge(sortedLeft sortedRight) return sortedList
bull This algorithm allocates extra space to complete its goal (not in-place)
bull Base case (size of input is less than 2 then return whatever is in input)
bull Split input into 2 ArrayLists
bull Recursive calls on left and right to get sorted versions and then merge them together
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
298
Cartoon Mistakes (13)
Composite shape class extending JPanelo Composite shape does not need to be a JPanelo Instead it should be a group of Shapes that is contained both
graphically and logically by the DrawingPanel
Composite shape class extending Shapeo This doesnrsquot provide any of the functionality that you need for a
composite shapeo Easier to not extend anything and write the necessary methods
yourself
398
Cartoon Mistakes (23)
Using containment instead of inheritance incorrectly For example we donrsquot want our DrawingPanel to contain a JPanel
We want our DrawingPanel to be a JPanel with added functionality
Putting an int into JLabelrsquos setText method JLabelrsquos setText method can only take in Strings If you want it to display an int you must convert the int to a
String passing in your int to the static method IntegertoString (see Javadocs for more info)
498
Cartoon Mistakes (33)
Making a separate JPanel for every different Shape in DrawingPanel This makes it difficult to manage all the components of your cartoon This kind of structure will make it hard to add on to your program if you
ever wanted to make edits Structuring your program so that it is extensible and can be scaled easily is very important in the real world
598
Continuation from last time
698
An Aside Java Autoboxingbull What do you do when you want to store an int
(or some other primitive) in an ArrayList in Java
bull You cannot use a generic with a primitive type So you can use the built-in class which is equivalent to that primitiveo int -gt Integero double -gt Double
bull If you use a built-in class that is equivalent to a primitive as a generic then with methods which take the generic type as a parameter you can pass in both an object of the built-in class or a primitive
bull Additionally the return values of methods which return a generic type can be stored in a variable of either the built-in class type or the primitive type
bull This is called Autoboxing
int x = 0ArrayListltIntegergt list = new ArrayListltIntegergt()listadd(x)int y = listget(0)
798
Merge Sort Summary
bull There are 2 main parts to this algorithmo First recursively divide list in half until
base case of one element is reached (one element is base case because a single element is always sorted)
o Then at each recursive level take each of the sorted sub-arrays and merge them together to make a sorted list
o Due to the recursion you have at the end a full sorted list
898
Merge Sort Animation
bull Unlike prior examples this animation sorts based on numbers directly not using height of the bar to visualize their value
998
Updated Merge Sort Codepublic ArrayListltIntegergt mergeSort(ArrayListltIntegergt input) ArrayListltIntegergt sortedList = new ArrayListltIntegergt() if (inputsize()lt2) for (int el input) sortedListadd(el) return sortedList
ArrayListltIntegergt left = new ArrayListltIntegergt() ArrayListltIntegergt right = new ArrayListltIntegergt() int middle = inputsize()2 for (int i =0 iltinputsize() i++) if (iltmiddle) leftadd(inputget(i)) else rightadd(inputget(i))
ArrayListltIntegergt sortedLeft = thismergeSort(left) ArrayListltIntegergt sortedRight = thismergeSort(right) sortedList = thismerge(sortedLeft sortedRight) return sortedList
bull This algorithm allocates extra space to complete its goal (not in-place)
bull Base case (size of input is less than 2 then return whatever is in input)
bull Split input into 2 ArrayLists
bull Recursive calls on left and right to get sorted versions and then merge them together
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
398
Cartoon Mistakes (23)
Using containment instead of inheritance incorrectly For example we donrsquot want our DrawingPanel to contain a JPanel
We want our DrawingPanel to be a JPanel with added functionality
Putting an int into JLabelrsquos setText method JLabelrsquos setText method can only take in Strings If you want it to display an int you must convert the int to a
String passing in your int to the static method IntegertoString (see Javadocs for more info)
498
Cartoon Mistakes (33)
Making a separate JPanel for every different Shape in DrawingPanel This makes it difficult to manage all the components of your cartoon This kind of structure will make it hard to add on to your program if you
ever wanted to make edits Structuring your program so that it is extensible and can be scaled easily is very important in the real world
598
Continuation from last time
698
An Aside Java Autoboxingbull What do you do when you want to store an int
(or some other primitive) in an ArrayList in Java
bull You cannot use a generic with a primitive type So you can use the built-in class which is equivalent to that primitiveo int -gt Integero double -gt Double
bull If you use a built-in class that is equivalent to a primitive as a generic then with methods which take the generic type as a parameter you can pass in both an object of the built-in class or a primitive
bull Additionally the return values of methods which return a generic type can be stored in a variable of either the built-in class type or the primitive type
bull This is called Autoboxing
int x = 0ArrayListltIntegergt list = new ArrayListltIntegergt()listadd(x)int y = listget(0)
798
Merge Sort Summary
bull There are 2 main parts to this algorithmo First recursively divide list in half until
base case of one element is reached (one element is base case because a single element is always sorted)
o Then at each recursive level take each of the sorted sub-arrays and merge them together to make a sorted list
o Due to the recursion you have at the end a full sorted list
898
Merge Sort Animation
bull Unlike prior examples this animation sorts based on numbers directly not using height of the bar to visualize their value
998
Updated Merge Sort Codepublic ArrayListltIntegergt mergeSort(ArrayListltIntegergt input) ArrayListltIntegergt sortedList = new ArrayListltIntegergt() if (inputsize()lt2) for (int el input) sortedListadd(el) return sortedList
ArrayListltIntegergt left = new ArrayListltIntegergt() ArrayListltIntegergt right = new ArrayListltIntegergt() int middle = inputsize()2 for (int i =0 iltinputsize() i++) if (iltmiddle) leftadd(inputget(i)) else rightadd(inputget(i))
ArrayListltIntegergt sortedLeft = thismergeSort(left) ArrayListltIntegergt sortedRight = thismergeSort(right) sortedList = thismerge(sortedLeft sortedRight) return sortedList
bull This algorithm allocates extra space to complete its goal (not in-place)
bull Base case (size of input is less than 2 then return whatever is in input)
bull Split input into 2 ArrayLists
bull Recursive calls on left and right to get sorted versions and then merge them together
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
498
Cartoon Mistakes (33)
Making a separate JPanel for every different Shape in DrawingPanel This makes it difficult to manage all the components of your cartoon This kind of structure will make it hard to add on to your program if you
ever wanted to make edits Structuring your program so that it is extensible and can be scaled easily is very important in the real world
598
Continuation from last time
698
An Aside Java Autoboxingbull What do you do when you want to store an int
(or some other primitive) in an ArrayList in Java
bull You cannot use a generic with a primitive type So you can use the built-in class which is equivalent to that primitiveo int -gt Integero double -gt Double
bull If you use a built-in class that is equivalent to a primitive as a generic then with methods which take the generic type as a parameter you can pass in both an object of the built-in class or a primitive
bull Additionally the return values of methods which return a generic type can be stored in a variable of either the built-in class type or the primitive type
bull This is called Autoboxing
int x = 0ArrayListltIntegergt list = new ArrayListltIntegergt()listadd(x)int y = listget(0)
798
Merge Sort Summary
bull There are 2 main parts to this algorithmo First recursively divide list in half until
base case of one element is reached (one element is base case because a single element is always sorted)
o Then at each recursive level take each of the sorted sub-arrays and merge them together to make a sorted list
o Due to the recursion you have at the end a full sorted list
898
Merge Sort Animation
bull Unlike prior examples this animation sorts based on numbers directly not using height of the bar to visualize their value
998
Updated Merge Sort Codepublic ArrayListltIntegergt mergeSort(ArrayListltIntegergt input) ArrayListltIntegergt sortedList = new ArrayListltIntegergt() if (inputsize()lt2) for (int el input) sortedListadd(el) return sortedList
ArrayListltIntegergt left = new ArrayListltIntegergt() ArrayListltIntegergt right = new ArrayListltIntegergt() int middle = inputsize()2 for (int i =0 iltinputsize() i++) if (iltmiddle) leftadd(inputget(i)) else rightadd(inputget(i))
ArrayListltIntegergt sortedLeft = thismergeSort(left) ArrayListltIntegergt sortedRight = thismergeSort(right) sortedList = thismerge(sortedLeft sortedRight) return sortedList
bull This algorithm allocates extra space to complete its goal (not in-place)
bull Base case (size of input is less than 2 then return whatever is in input)
bull Split input into 2 ArrayLists
bull Recursive calls on left and right to get sorted versions and then merge them together
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
598
Continuation from last time
698
An Aside Java Autoboxingbull What do you do when you want to store an int
(or some other primitive) in an ArrayList in Java
bull You cannot use a generic with a primitive type So you can use the built-in class which is equivalent to that primitiveo int -gt Integero double -gt Double
bull If you use a built-in class that is equivalent to a primitive as a generic then with methods which take the generic type as a parameter you can pass in both an object of the built-in class or a primitive
bull Additionally the return values of methods which return a generic type can be stored in a variable of either the built-in class type or the primitive type
bull This is called Autoboxing
int x = 0ArrayListltIntegergt list = new ArrayListltIntegergt()listadd(x)int y = listget(0)
798
Merge Sort Summary
bull There are 2 main parts to this algorithmo First recursively divide list in half until
base case of one element is reached (one element is base case because a single element is always sorted)
o Then at each recursive level take each of the sorted sub-arrays and merge them together to make a sorted list
o Due to the recursion you have at the end a full sorted list
898
Merge Sort Animation
bull Unlike prior examples this animation sorts based on numbers directly not using height of the bar to visualize their value
998
Updated Merge Sort Codepublic ArrayListltIntegergt mergeSort(ArrayListltIntegergt input) ArrayListltIntegergt sortedList = new ArrayListltIntegergt() if (inputsize()lt2) for (int el input) sortedListadd(el) return sortedList
ArrayListltIntegergt left = new ArrayListltIntegergt() ArrayListltIntegergt right = new ArrayListltIntegergt() int middle = inputsize()2 for (int i =0 iltinputsize() i++) if (iltmiddle) leftadd(inputget(i)) else rightadd(inputget(i))
ArrayListltIntegergt sortedLeft = thismergeSort(left) ArrayListltIntegergt sortedRight = thismergeSort(right) sortedList = thismerge(sortedLeft sortedRight) return sortedList
bull This algorithm allocates extra space to complete its goal (not in-place)
bull Base case (size of input is less than 2 then return whatever is in input)
bull Split input into 2 ArrayLists
bull Recursive calls on left and right to get sorted versions and then merge them together
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
698
An Aside Java Autoboxingbull What do you do when you want to store an int
(or some other primitive) in an ArrayList in Java
bull You cannot use a generic with a primitive type So you can use the built-in class which is equivalent to that primitiveo int -gt Integero double -gt Double
bull If you use a built-in class that is equivalent to a primitive as a generic then with methods which take the generic type as a parameter you can pass in both an object of the built-in class or a primitive
bull Additionally the return values of methods which return a generic type can be stored in a variable of either the built-in class type or the primitive type
bull This is called Autoboxing
int x = 0ArrayListltIntegergt list = new ArrayListltIntegergt()listadd(x)int y = listget(0)
798
Merge Sort Summary
bull There are 2 main parts to this algorithmo First recursively divide list in half until
base case of one element is reached (one element is base case because a single element is always sorted)
o Then at each recursive level take each of the sorted sub-arrays and merge them together to make a sorted list
o Due to the recursion you have at the end a full sorted list
898
Merge Sort Animation
bull Unlike prior examples this animation sorts based on numbers directly not using height of the bar to visualize their value
998
Updated Merge Sort Codepublic ArrayListltIntegergt mergeSort(ArrayListltIntegergt input) ArrayListltIntegergt sortedList = new ArrayListltIntegergt() if (inputsize()lt2) for (int el input) sortedListadd(el) return sortedList
ArrayListltIntegergt left = new ArrayListltIntegergt() ArrayListltIntegergt right = new ArrayListltIntegergt() int middle = inputsize()2 for (int i =0 iltinputsize() i++) if (iltmiddle) leftadd(inputget(i)) else rightadd(inputget(i))
ArrayListltIntegergt sortedLeft = thismergeSort(left) ArrayListltIntegergt sortedRight = thismergeSort(right) sortedList = thismerge(sortedLeft sortedRight) return sortedList
bull This algorithm allocates extra space to complete its goal (not in-place)
bull Base case (size of input is less than 2 then return whatever is in input)
bull Split input into 2 ArrayLists
bull Recursive calls on left and right to get sorted versions and then merge them together
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
798
Merge Sort Summary
bull There are 2 main parts to this algorithmo First recursively divide list in half until
base case of one element is reached (one element is base case because a single element is always sorted)
o Then at each recursive level take each of the sorted sub-arrays and merge them together to make a sorted list
o Due to the recursion you have at the end a full sorted list
898
Merge Sort Animation
bull Unlike prior examples this animation sorts based on numbers directly not using height of the bar to visualize their value
998
Updated Merge Sort Codepublic ArrayListltIntegergt mergeSort(ArrayListltIntegergt input) ArrayListltIntegergt sortedList = new ArrayListltIntegergt() if (inputsize()lt2) for (int el input) sortedListadd(el) return sortedList
ArrayListltIntegergt left = new ArrayListltIntegergt() ArrayListltIntegergt right = new ArrayListltIntegergt() int middle = inputsize()2 for (int i =0 iltinputsize() i++) if (iltmiddle) leftadd(inputget(i)) else rightadd(inputget(i))
ArrayListltIntegergt sortedLeft = thismergeSort(left) ArrayListltIntegergt sortedRight = thismergeSort(right) sortedList = thismerge(sortedLeft sortedRight) return sortedList
bull This algorithm allocates extra space to complete its goal (not in-place)
bull Base case (size of input is less than 2 then return whatever is in input)
bull Split input into 2 ArrayLists
bull Recursive calls on left and right to get sorted versions and then merge them together
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
898
Merge Sort Animation
bull Unlike prior examples this animation sorts based on numbers directly not using height of the bar to visualize their value
998
Updated Merge Sort Codepublic ArrayListltIntegergt mergeSort(ArrayListltIntegergt input) ArrayListltIntegergt sortedList = new ArrayListltIntegergt() if (inputsize()lt2) for (int el input) sortedListadd(el) return sortedList
ArrayListltIntegergt left = new ArrayListltIntegergt() ArrayListltIntegergt right = new ArrayListltIntegergt() int middle = inputsize()2 for (int i =0 iltinputsize() i++) if (iltmiddle) leftadd(inputget(i)) else rightadd(inputget(i))
ArrayListltIntegergt sortedLeft = thismergeSort(left) ArrayListltIntegergt sortedRight = thismergeSort(right) sortedList = thismerge(sortedLeft sortedRight) return sortedList
bull This algorithm allocates extra space to complete its goal (not in-place)
bull Base case (size of input is less than 2 then return whatever is in input)
bull Split input into 2 ArrayLists
bull Recursive calls on left and right to get sorted versions and then merge them together
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
998
Updated Merge Sort Codepublic ArrayListltIntegergt mergeSort(ArrayListltIntegergt input) ArrayListltIntegergt sortedList = new ArrayListltIntegergt() if (inputsize()lt2) for (int el input) sortedListadd(el) return sortedList
ArrayListltIntegergt left = new ArrayListltIntegergt() ArrayListltIntegergt right = new ArrayListltIntegergt() int middle = inputsize()2 for (int i =0 iltinputsize() i++) if (iltmiddle) leftadd(inputget(i)) else rightadd(inputget(i))
ArrayListltIntegergt sortedLeft = thismergeSort(left) ArrayListltIntegergt sortedRight = thismergeSort(right) sortedList = thismerge(sortedLeft sortedRight) return sortedList
bull This algorithm allocates extra space to complete its goal (not in-place)
bull Base case (size of input is less than 2 then return whatever is in input)
bull Split input into 2 ArrayLists
bull Recursive calls on left and right to get sorted versions and then merge them together
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1098
Merge Codepublic ArrayListltIntegergt merge(ArrayListltIntegergt left ArrayListltIntegergt right) ArrayListltIntegergt result = new ArrayListltIntegergt() int leftIndex = 0 int rightIndex = 0 while (leftIndex lt leftsize() ampamp rightIndex lt rightsize()) if (leftget(leftIndex) lt= rightget(rightIndex))
resultadd(leftget(leftIndex)) leftIndex++ else
resultadd(rightget(rightIndex)) rightIndex++ if (leftIndex lt leftsize()) add any remaining elements for (int i=leftIndex iltleftsize() i++) resultadd(leftget(i)) do same thing for right side return result
bull Add the elements from the two sequences in increasing order
bull If there are elements left that you havenrsquot added add the remaining elements to your result
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1198
MergeSort Runtime Analysisbull The operation on each level
(splitting and merging) is a sequential pass through each number hence O(n)
bull Splitting and merging each take log2n levels of recursion so runtime is n 2 log2n = O(nlog2n) which is much better than O(n2) O(n)
O(log2n)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1298
Lecture 16Linked Lists
C S 1 5
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1398
Different Data Structures for Collections for Different Use Cases (12)
There are many data structures to store a collection of elements
ArrayLists are called that because they implement the List interface (many of whose methods we introduced in lecture) and they are implemented using Arrays
We can define a different building block called the Linked List which is better than Arrays for some use cases by avoiding data movement for insertion and deletion
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1498
Different Data Structures for Collections for Different Use Cases (22)
Using this building block of a linked list of nodes we can construct a number of higher level abstractions eg a NodeList to parallel the ArrayList Stacks Queues etc covered in next lecture
There are many data structures to store a collection of elementso choose based on the way data is accessed and stored in your
algorithmo The access and store operations of different data structures
can have very different impacts on an algorithmrsquos overall efficiency
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1598
What is a Linked List (12)
A collection of linked nodes that form a sequence of elements o as with Arrays and ArrayLists it can represent an unordered
set or an ordered sequence of your data ie your algorithm can take advantage of fact that elements are stored sequentially or not
Linked List holds references to the first node (head) and last node (tail)
C S 1 5
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1698
What is a Linked List (22)
Each node holds an element and a reference to the next node in the list
Most methods will involveo ldquopointer-chasingrdquo through the Linked List (for search and finding
the right place to deleteinsert) andor io breaking and resetting the LL (to delete and insert)
But there wonlsquot be data movement
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1798
Ex HTA Linked List
LinkedListltHTAgt
NodeltHTAgt _head NodeltHTAgt _tail
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
NodeltHTAgt
NodeltHTAgt _next
HTA _data
Ardra Gregory Sonia
null
Note that this is an instance diagram not a class diagram because it has specific values
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1898
Arrays
indexed (allows explicit access to nth item)
indices of other items donrsquot change if an item is replaced or deleted from a specific index but will change if new item is inserted at an index before end
cannot change size dynamically
ArrayLists
indexed (allows explicit access to nth item)
indices of other items are updated following an inserted or deleted item
can growshrink dynamically
Java uses an Array as the underlying data structure
Linked Lists
not indexed In order to access the nth element must start at the beginning and go to the next node n times rarr no random access
can growshrink dynamically
use nodes instead of arrays
can insertremove in middle of list without data movement throughout rest of list
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
1998
Linked List Implementations Find javautil implementation at httpdocsoraclecomjavase7docsapijavautilLinkedListhtml
For now wersquoll define our own data structure MyLinkedListo Difference between MyLinkedList and Javarsquos implementation is that
Java uses something like our MyLinkedList to build a more advanced data structure While there is overlap there are also differences in the methods provided their names and their return types
MyLinkedList is a building block for more specialized versions Stacks Queues Sorted Linked Listshellip
We start by defining a Singly Linked List both for unsorted and sorted items then we will define a Doubly Linked List
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2098
Generic Unsorted Singly Linked List (13)
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList() public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
more on next slide
Generic type parameter
bull Constructor initializes instance variableso _head and _tail are initially
set to null
bull addFirst creates first node and sets _head to reference it
bull addLast appends a Node to the end of the list and sets _tail to it
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2198
Generic Unsorted Singly Linked List (23) public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
still more on next slide
bull removeFirst removes first Node and returns element
bull removeLast remove last Node and returns element
bull remove removes the node containing the element el and returns it
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2298
Generic Unsorted Singly Linked List (23) public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull search finds and returns node containing el (note difference with removes)
bull size returns _size of list
bull isEmpty checks if list is empty
bull getHeadgetTail return a reference to the headtail node of the list
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2398
Generic Singly Linked List Overview
public class MyLinkedListltTypegt private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt addFirst(Type el)
public NodeltTypegt addLast(Type el)
public Type removeFirst()
public Type removeLast()
public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
Generic type parameter
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2498
The Node Class Node class holds its element and
a reference to the next Node
Its methods are made up of mutators and accessors for these variables
Thatrsquos it
public class NodeltTypegt private Type _elementprivate NodeltTypegt _next
public Node(Type element) _element = element_next = null
public void setNext(NodeltTypegt next)
_next = next
public NodeltTypegt getNext() return _next
similar mutator and accessor
method for _element are elided
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2598
Ex A pile of books (12)
Letrsquos use a linked list to model a simple pile (ie set) of books
The Elements in our pile will be of type Booko have titles authors dates and
ISBN numberso we want a list that can store
anything that ldquois ardquo Book
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2698
Ex A pile of books (22)
Book combines Authors Titles and ISBNs
We will create and use Books to store all elements from the pile in a linked list
Book
NodeltTypegt _nextString _authorString _titleint _isbn
getAuthor()getTitle()getISBN()hellip
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2798
Book Class
Nothing newhellip
Constructor stores the author date and ISBN number of book as instance variables
getISBN() returns _isbn
public class Book private String _author private String _title private int _isbn
public Book(String author String title int
isbn) _author = author _title = title _isbn = isbn
public int getISBN() return _isbn
other methods elided
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2898
PileOfBooks Class
We can use a MyLinkedList of books as the underlying data structure for our PileOfBooks class
Book is our generic Type
Instantiating a MyLinkedList is entirely similar to instantiating an ArrayList
public class PileOfBooks private MyLinkedListlt gt _books public PileOfBooks() _books = new
MyLinkedListltBookgt()
There could be many more methods here
Book
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
2998
addFirst ndash list is empty
If list is empty _head and _tail will be null
Create a new NodeltTypegt
Set the new nodersquos _next variable to the current _head (in this case null)
Set the _head and _tail variables to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head_tail
null_tail null
For simplicity we elide initialization of _element and showing of what it points to
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3098
addFirst - not empty
Create a new node
set its _next variable to the current _head (in this case some previously added node that heads the list)
Set the _head variable to the new node
NodeltTypegt
NodeltTypegt _nextType_element
new node
_head
_head
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
_tail
hellip
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3198
Constructor and addFirst Methodspublic MyLinkedList() _head = null
_tail = null _size = 0
public NodeltTypegt addFirst(Type el) _size++ NodeltTypegt newNode = new
NodeltTypegt(el) newNodesetNext(_head) _head = newNode
if (size == 1)_tail = newNode
return newNode
bull Constructor o initialize instance
variables
bull addFirst methodo Increment _size by 1o create new nodeo Set newNodersquos next
pointer to first nodeo _head now is set to
point to newNode o if _size is 1 _tail also
points to newNode
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3298
Constructor and addFirst Runtimepublic MyLinkedList() _head = null 1 op _tail = null 1 op _size = 0 1 op
public NodeltTypegt addFirst(Type el) _size++ 1 op NodeltTypegt newNode = new NodeltTypegt(el) 1 op newNodesetNext(_head) 1 op _head = newNode 1 op
if (size == 1) 1 op_tail = newNode 1 op
return newNode 1 op
rarr addFirst(Type el) is O(1)
rarr constructor is O(1)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3398
addLast Method _tail already points to the last
node in the list
Create a new NodeltTypegt
set _tailrsquos _next pointer to the new node
then update _tail to be the new node
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_head
_tail
_tail
hellip
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3498
addLast Methodpublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) if(_size == 0) _head = newNode
_tail = newNode else
_tailsetNext(newNode)_tail = newNode
_size++ return newNode
Edge Caseo if list is empty set the _head
and _tail variables to the newNode
General Caseo set _next variable of
current last node (to which _tail is pointing) to new last node and then set _tail to that new last node
o the new nodersquos _next variable already points to null
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3598
addLast Runtimepublic NodeltTypegt addLast(Type el) NodeltTypegt newNode = new NodeltTypegt(el) 1 op if(_size == 0) 1 op _head = newNode 1 op
_tail = newNode 1 op else
_tailsetNext(newNode) 1 op_tail = newNode 1 op
_size++ 1 op return newNode 1 op
rarr addLast(Type el) is O(1)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3698
size and isEmpty Methods
public int size()return _size
public boolean isEmpty() return _size == 0
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3798
size and isEmpty Runtime
public int size()return _size 1 op
public boolean isEmpty() return _size == 0 1 op
rarr size() is O(1)
rarr isEmpty() is O(1)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3898
removeFirst Method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
bull Remove reference to original first node by setting _head variable to first nodersquos successor node via firstrsquos _next
bull Node to remove is garbage-collected at the termination of the method
_head
_head
garbage-collected
hellip
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
3998
removeFirst Method
public Type removeFirst() if(_size==0)
Systemoutprintln(ldquoList is emptyrdquo)
return null
Type removed = _headgetElement() _head = _headgetNext() _size-- if(_size==0)
_tail = null return removed
bull Edge case for empty list o println is optional one way to
handle error checking caller should check for null in any case
bull Store element from first node to be removed
bull Then unchain first node by resetting _head to point to first nodersquos successor
bull If list is now empty set _tail to null
bull Node to remove is garbage-collected at methodrsquos end
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4098
removeFirst Runtimepublic Type removeFirst() if(_size==0) 1 op
Systemoutprintln(ldquoList is emptyrdquo) 1 opreturn null 1 op
Type removed = _headgetElement() 1 op _head = _headgetNext() 1 op _size-- 1 op if(_size==0) 1 op
_tail = null 1 op return removed 1 op
rarr removeFirst(Type el) is O(1)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4198
removeLast Method As with removeFirst remove
node by removing any references to it
Pointer-chase to get predecessor to _tail node and reset predecessorrsquos _next instance variable to null
last node is thereby garbage- collected
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType_element
NodeltTypegt
NodeltTypegt _nextType _element
last node
null
hellip
garbage-collected
NodeltTypegt
NodeltTypegt _nextType_element
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4298
removeLast Method
public Type removeLast() Type removed = null
if(_size==0)Systemoutprintln(ldquoList is emptyrdquo)
else if(_size==1) removed = _headgetElement() _head = null
_tail = null _size--
else classic pointer-chasing loop Node curr = _head Node prev = null
while(currgetNext()=null) bop the pointers
prev = curr curr = currgetNext() removed = currgetElement() prevsetNext(null) unlink last _tail = prev
_size-- return removed
bull Edge case(s)o Canrsquot delete from an empty list o If there is only one node null the
_head and _tail references
bull General caseo Iterate (ldquopointer-chaserdquo) through listo After loop ends prev will point to
node just before last node and curr will point to last node
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4398
removeLast Runtime
rarr removeLast(Type el) is O(n)
public Type removeLast() 1 op Type removed = null 1 op if(_size==0) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op else if(_size==1) 1 op removed = _headgetElement() 1 op _head = null 1 op _tail = null 1 op _size-- 1 op else
Node curr = _head 1 op Node prev = null 1 op while(currgetNext()=null) n ops
prev = curr 1 op curr = currgetNext() 1 op removed = currgetElement() 1 op prevsetNext(null) 1 op _tail = prev 1 op _size-- 1 op return removed 1 op
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4498
search Method
What if we want to find a certain book in the pile of books
Must compare each book with the one we are looking foro But In order to do this we first need a way to check for the
equality of two elements
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4598
Javarsquos ComparableltTypegt interface (13)
Previously we used == to check if two things are equalo This only works correctly for primitive data types (eg int) or when
we are comparing two variables referencing the exact same objecto To compare Strings we need a different way to compare things
We can implement the ComparableltTypegt interface provided by Java
Must define compareTo method which returns an int
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4698
The ComparableltTypegt interface is parameterized using generics
You call compareTo on a variable of the same type as specified in the implementation of the interface (Book in our case)
public interface ComparableltTypegt public int compareTo (Type toCompare)
Javarsquos ComparableltTypegt interface (23)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4798
Javarsquos ComparableltTypegt interface (33)
compareTo method must return an into negative if object on which compareTo is called is
less than object passed in as a parametero 0 if object is equal to object passed ino positive if this object is greater than object passed in
as a parametero compareTo not only used for numerical
comparisons - could be used for alphabetical comparisons as well
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4898
Comparable Book Class
Book class now implements ComparableltBookgt
compareTo is defined according to the specifications o returns number that is
gt0 0 or lt0 depending on the ISBN numbers
public class Book implements ComparableltBookgt variable declarations eg _isbn
elided
public Book(String author String title int isbn)
variable initializations elided
public javautildate getISBN() return _isbn
other methods elided
public int compareTo(Book toCompare) return (_isbn - toComparegetISBN())
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
4998
ldquoComparablerdquo Singly Linked List public class MyLinkedListltType extends
ComparableltTypegtgt private NodeltTypegt _head
private NodeltTypegt _tail private int _size public MyLinkedList() public NodeltTypegt addFirst(Type el) public NodeltTypegt addLast(Type el)
other methods elided
Using keyword extends in this way ensures that Type implements ComparableltTypegt Note nested ltgt and that
extends is used differently
All elements stored in MyLinkedList must now have compareTo method for Type
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5098
Search Method public NodeltTypegt search(Type el) NodeltTypegt curr = _head
while(curr = null) if(currgetElement()compareTo(el) ==
0) return curr curr = currgetNext() bop pointer
return null
loops through list
if a nodersquos element is the same as the input return curr (note returning always exits a method)
if no elements match return null
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5198
Search Runtime
rarr search(Type el) is O(n)
public NodeltTypegt search(Type el) NodeltTypegt curr = _head 1 op
while(curr = null) n ops if(currgetElement()compareTo(el) == 0) 1 op return curr 1 op
curr = currgetNext() 1 op
return null 1 op
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5298
remove Method
We have implemented methods to remove the first and the last elements of MyLinkedList
What if we want to remove any element from MyLinkedList
Letrsquos write a general remove methodo This will be similar to the search algorithm
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5398
remove Method loop through nodes until find one
whose _element matches itemToRemove
ldquojump overrdquo node by re-linking predecessor of node (again using looprsquos prev pointer) to successor of node (via its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
hellip
hellip
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5498
remove Method
bull Edge Case(s)o Again Canrsquot delete from an
empty list o If removing first itemlast
item use removeFirstremoveLast
bull General Caseo Iterate over list until
itemToRemove is foundo Again need prev so we
can re-link predecessor of curr
public Type remove(Type itemToRemove) if (thisisEmpty()) Systemoutprintln(ldquoList is emptyrdquo) return null if (itemToRemovecompareTo(_headgetElement()) == 0) return thisremoveFirst() if (itemToRemovecompareTo(_tailgetElement()) == 0)
return thisremoveLast() NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) pointer-chasing loop to find el if (itemToRemovecompareTo(currgetElement()) == 0) prevsetNext(currgetNext())jump over node
_size-- decrement size return currgetElement() prev = curr if not found bop pointers curr = currgetNext() return null return null if itemToRemove is not found
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5598
remove Runtime
rarr remove(Type itemToRemove) is O(n)
public Type remove(Type itemToRemove) if (thisisEmpty()) 1 op Systemoutprintln(ldquoList is emptyrdquo) 1 op return null if (itemToRemovecompareTo(_headgetElement()) == 0) 1 op return thisremoveFirst() O(1) if (itemToRemovecompareTo(_tailgetElement()) == 0) 1 op
return thisremoveLast() O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement()) == 0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op
return currgetElement() 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5698
Ex A sorted bookshelf Faster to find (and
remove) books in a sorted bookshelf
Use a sorted linked listo makes several of our
methods more efficient search insert delete
Sort in increasing ordero maintain sort order when
inserting
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5798
A Generic Sorted Singly Linked List public class MySortedLinkedListltTypegt
private NodeltTypegt _headprivate NodeltTypegt _tailprivate int _sizepublic MyLinkedList()
public NodeltTypegt insert(Type el) public Type remove(Type el)
public NodeltTypegt search(Type el)
public int size()
public boolean isEmpty()
public NodeltTypegt getHead()
public NodeltTypegt getTail()
hellip
bull Slightly different collection of methods
o addFirst and addLast replaced by general insert
bull Many methods whose signatures havenrsquot changed will have different implementation because of more efficient loop termination used in search and remove
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5898
search Method [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head while(curr = null)
have we found it if (toFindcompareTo(currgetElement()) == 0) return curr
are we past it Currrsquos element gt toFind else if (toFindcompareTo(currgetElement()) lt 0) return null havenrsquot found it bop the ptr curr = currgetNext()
return null
bull Must iterate through list until toFind is found
bull Compare toFind to currrsquos elemento if == wersquore done
bull If currrsquos element is greater than toFind stop searcho we know that any following nodesrsquo
elements will also be greater since list is sorted
o note order of operands dictates sign of test ndash be careful
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
5998
search Runtime [for Sorted Linked Lists]
public NodeltTypegt search(Type toFind) NodeltTypegt curr = _head 1 op while(curr = null) n ops
if (toFindcompareTo(currgetElement()) == 0) 1 op return curr 1 op
else if (toFindcompareTo (currgetElement()) lt 0) 1 op
return null 1 op
curr = currgetNext() 1 op
return null 1 op rarr search(Type toFind) is O(n)
While the else if statement will often improve performance it does not affect Big-O run time (Big O describes the worst case)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6098
What did Sorting Buy Usbull Search still O(n) Not better worst-case performance but better for
normal cases because you can usually stop earlier for items not in the list
bull This comes at the cost of having to maintain sort order ie by having to insert ldquoin the right placerdquo (next slide)
bull So if you do a lot of searching compared to insertion and deletion this efficiency would pay off conversely if you do a lot of adding and deleting compared to searching it wouldnrsquot since yoursquod use the simple O(1) insertFirst or insertLasthellip
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6198
insert method Once again iterate through
nodes with a while loop keeping track of current and previous nodes
Unlike insertion into unsorted linked list there is one correct spot in list for new node
End iteration if current nodersquos value is greater than new nodersquos value ndash this is the spot
Set _next pointers of new node and previous node
null
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
new node
_curr
_prev
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6298
insert Method [for Sorted Linked Lists]
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) node for
newItem if(thisisEmpty())
_head = toAdd_tail = toAdd
else NodeltTypegt curr = _head NodeltTypegt prev = null while(curr = null) pointer-chasing iterator if (newItemcompareTo(currgetElement()) gt 0) prev = curr curr = currgetNext() else found the spot toAddsetNext(curr) if(prev = null) prevsetNext(toAdd) else prev is null at front of list _head = toAdd
_size++return toAdd
prevsetNext(toAdd) to insert node at end_tail = toAdd_size++
return toAdd
bull Edge caseo If list is empty all we
have to do is reset _head_tail
bull General caseo Iterate over lists until
currrsquos element is greater than newItem
o Need looprsquos prev so we can re-link list to integrate the new node
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6398
insert Runtime [for Sorted Linked Lists]
rarr insert(Type newItem) is O(n)
public NodeltTypegt insert(Type newItem) NodeltTypegt toAdd = new NodeltTypegt(newItem) 1 op if(thisisEmpty()) 1 op
_head = toAdd 1 op_tail = toAdd 1 op
else NodeltTypegt curr = _head 1 op NodeltTypegt prev = null 1 op while(curr = null) pointer-chasing iterator n ops if (newItemcompareTo(currgetElement()) gt 0) 1 op prev = curr 1 op curr = currgetNext() 1 op else toAddsetNext(curr) 1 op if(prev = null) 1 op prevsetNext(toAdd) 1 op else _head = toAdd 1 op
_size++ 1 opreturn toAdd 1 op
prevsetNext(toAdd) 1 op_tail = toAdd 1 op_size++ 1 op
return toAdd 1 op
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6498
remove Method[for Sorted Linked Lists]
loop through nodes until find one whose _element matches itemToRemoveo since list is sorted we can
end loop early ndash stay tuned
re-link predecessor of node (again using a previous node) to successor of node (its _next reference)
with no more reference to node it is garbage collected at the termination of the method
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegtNodeltTypegt _nextType _element
garbage-collected
to remove
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6598
remove Method [for Sorted Linked Lists]
bull Edge Case(s)o If list is empty return nullo If itemToRemove is the
_head_tail use same code as removeFirstremoveLast in MyLinkedList
bull General case o Iterate over list until either
itemToRemove is found in which case we return the found item before removing its node
or the elements in the list are larger than itemToRemove in which case we return null
or we reach the end of the list in which case we return null
public Type remove(Type itemToRemove) if(thisisEmpty()) return null if(itemToRemovecompareTo(_headgetElement())==0)
elided same as MyLinkedListrsquos removeFirst code if(itemToRemovecompareTo(_tailgetElement())==0)
elided same as MyLinkedListsrsquos removeLast code NodeltTypegt curr = _headgetNext() NodeltTypegt prev = _head while(curr = null) if (itemToRemovecompareTo(currgetElement())==0) prevsetNext(currgetNext()) jump over node _size-- return currgetElement() curr still points to it else if(itemToRemovecompareTo(currgetElement()) lt 0) return null prev = curr bop pointers iterate curr = currgetNext() return null
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6698
remove Runtime [for Sorted Linked Lists]
rarr remove(Type itemToRemove) is O(n)
Again the else if statement will often improve performance but it does not affect Big-O run time
public Type remove(Type itemToRemove) 1 op if(thisisEmpty()) 1 op
return null 1 op if(itemToRemovecompareTo(_headgetElement())==0) 1 op
elided same as MyLinkedListrsquos removeFirst code O(1) if(itemToRemovecompareTo(_tailgetElement())==0) 1 op
elided same as MyLinkedListsrsquos removeLast code O(n) NodeltTypegt curr = _headgetNext() 1 op NodeltTypegt prev = _head 1 op while(curr = null) n ops if (itemToRemovecompareTo(currgetElement())==0) 1 op prevsetNext(currgetNext()) 1 op _size-- 1 op return currgetElement() 1 op else if(itemToRemovecompareTo(currgetElement()) lt 0) 1 op return null 1 op prev = curr 1 op curr = currgetNext() 1 op return null 1 op
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6798
Doubly Linked List (12)
Is there an easierfaster way to get to the previous node for ease in removing a nodeo with Doubly Linked Lists nodes have references both to the
next node and the previous nodeo can traverse the list both backwards and forwards ndash Linked List
stores reference to front of the list with _head and back of the list with _tail
o have to modify the Node class to have two pointers _next and _prev
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6898
Doubly Linked List (12)
bull For Singly Linked List the processing typically goes from first to last node eg search finding the place to insert or delete
bull Sometimes particularly for a sorted list1 you want to be able to go in the opposite direction o Eg sort students on their final grades Find the lowest numeric
grade that will be recorded as an ldquoArdquo Now ask who is close to getting an ldquoArdquo ie borderline
C S 1 5
1 Like Singly Linked Lists Doubly Linked Lists can be sorted or unsorted We only discuss the sorted version here
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
6998
Doubly Linked List (22)
bull This kind of backing-up canrsquot easily be done with the Singly Linked List implementation we have so faro Wersquod have to build our own specialized search method which would scan
from the _head and be at a minimum O(n)
bull It is trivial for Doubly Linked Listso find student with the lowest ldquoArdquo using searcho use the _prev pointer which points to the predecessor of a node ( O(1) )
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7098
Remove method [for Sorted Doubly Linked List]
bull This is pseudo-code for a remove method for a Sorted Doubly Linked Listo Note that we are using dot-
notation for variables ndash a common practice for pseudo-code
bull Other methods are analogous
remove(Type t) Node n = search(t) set n_prevrsquos _next variable to n_next set n_nextrsquos _prev variable to n_prev return nrsquos Type
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7198
Node [for Doubly Linked Lists]
public class NodeltTypegt private Type _element private NodeltTypegt _next private NodeltTypegt _prev New public Node(Type element)
_element=element_next=null_prev = null
public void setNext(NodeltTypegt
next) _next=next
public NodeltTypegt getNext() return _next
public void setPrev(NodeltTypegt
prev)_prev = prev
public Node ltTypegt getPrev()
return _prev
Mutator and accessor method for _element are elided
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7298
Summary of Linked Listsbull Wersquove introduce four different implementations of Linked Lists
bull They can be grouped into two categorieso Unsorted vs Sorted Linked List
bull Unsorted Linked List has two different implementations with identical method signatures and return typeso Unsorted Singly vs Unsorted Doubly Linked List
bull Sorted Linked List also has two different implementations with identical method signatures and return typeso Sorted Singly vs Sorted Doubly Linked List
bull Implementation matters While an Unsorted Singly Linked List and an Unsorted Doubly Linked List have the same functionality they have different runtimes for their methodso pick implementation based on how you will use the data structure
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7398
Circular Doubly Linked Lists
bull No beginning or end
bull Example Rolodex
bull In operating systems these structures are called rings
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7498
When to use a Linked List
You might use a Linked List ifo do not need random accesso need constant time insertionremoval at head or tail of listo often need to insert elements into the interior of the listo do not know how many elements you will store a priori
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7598
Linked List Exercises
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7698
How To Build A Node List
Now that we have a building block there are a number of methods we can implement to make a higher-level NodeList that implements Javarsquos List interface (like ArrayList does) - note List is very generalhellip
Main addition List mandates is to support indexing into the NodeList Letrsquos write one of the simpler oneso get(int i) method that returns Type at that index
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7798
search Private Helper Methodpublic class NodeListltTypegt
constructor elidedprivate NodeltTypegt search(int i) if(i gt= _size || i lt 0)
Systemoutprintln(ldquoInvalid indexrdquo)return null
NodeltTypegt curr = _head for loop stops at i pointer-chase till then for(int counter = 0 counter lt i counter++)
curr = currgetNext()
return curr
bull First define a search helper method to return node at a particular index
bull Want to use this helper method in the class but donrsquot want to expose found nodes publicly that would violate encapsulation - make helper private
bull If list has no node at provided index return null (print line is an optional error message)
bull Otherwise iterate through list until node at desired index is reached and return that node
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7898
search Private Helper Method Runtimeprivate NodeltTypegt search(int i) if(i gt= _size|| i lt 0) 1 op Systemoutprintln(ldquoInvalid indexrdquo) 1 op return null 1 op
NodeltTypegt curr = _head 1 op for(int counter = 0 counter lt i counter++) n ops
curr = currgetNext() 1 op return curr 1 op
rarr search(int i) is O(n)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
7998
Public Wrapper Method
bull Finally letrsquos write the publicly accessible wrapper code for the NodeListrsquos get method o this shows a very common pattern
of ldquothin wrappersrdquo over private code
inside NodeListpublic Type get(int i)
return thissearch(i)getElement()
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8098
An Exercise (ldquoCS16-Stylerdquo common job interview question)
Write a method that reverses the order of a MyLinkedListNodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element
NodeltTypegt
NodeltTypegt _nextType _element1
21
2
3
3
_head
_head
_tail
_tail
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8198
Solution A public MyLinkedListltTypegt reverse(MyLinkedListltTypegt toReverse) if(toReversesize()lt2)
return toReverse
MyLinkedListltTypegt newList = new MyLinkedListltTypegt()
int origSize = toReversesize()
while(newListsize() lt origSize) newListaddFirst(toReverseremoveFirst())
return newList
bull If list is empty or has 1 node return list
bull Otherwise create a new list of same type as input list
bull Iterate through input list removing first element each time and adding it as first element of new list
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8298
Solution B (12)
Is there a better way
First algorithm reversed in O(n) timeo but it wasnrsquot in place ndash (we had to create a new list)
We can write a method within MyLinkedList that reverses itself without creating new nodeso Still O(n) but in place and therefore more efficient
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8398
Solution B (22)public void reverse() NodeltTypegt prev = null NodeltTypegt curr = _head NodeltTypegt next = null _tail = _headset tail to head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_head = prev
bull Keep track of previous current and next node
bull While current node isnrsquot null iterate through nodes resetting node pointers in reverse
o in doing so must be careful not to delete any references further on in the list
bull Finally set the _head pointer to what had been the last node (held in the prev variable)
bull If the list is empty curr will be null so the loop will never begin and _head will continue to point to null
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8498
Solution B Walkthrough 115
A B C
prev = null
curr
next = null
_head _tail
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8598
Solution B Walkthrough 215
A B C
prev = null
curr
next = null
_head
_tail = _head
_tail
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8698
Solution B Walkthrough 315
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8798
Solution B Walkthrough 415
A B C
prev = null
curr next
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8898
Solution B Walkthrough 515
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
8998
Solution B Walkthrough 615
A B C
null
curr
nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9098
Solution B Walkthrough 715
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9198
Solution B Walkthrough 815
A B C
null
curr nextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9298
Solution B Walkthrough 915
A B C
null
curr next
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9398
Solution B Walkthrough 1015
A B C
null
currnextprev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9498
Solution B Walkthrough 1115
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9598
Solution B Walkthrough 1215
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9698
Solution B Walkthrough 1315
A B C
null
curr
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9798
Solution B Walkthrough 1415
A B C
null
curr = null
next = null
prev
_head
while(curr=null) next = currgetNext() currsetNext(prev) prev = curr curr = next
_tail
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9898
Solution B Walkthrough 1515
A B C
null
curr = null
next = null
prev
_head
_head = prev
_tail
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)
9998
Announcements bull DoodleJump early deadline is Friday 1031 at 1000PM
bull On Time is Sunday 112 at 1159PM
bull Late is Tuesday 114 at 1159PM
bull Tomorrow at 4PM is the Undergraduate TA Info Session on the 3rd floor atrium of the CIT
bull On Thursday wersquore celebrating Halloween with a skit
o Everybody is invited to come in costume
bull If you are interested in being a TA next semester you should attend (by completing CS15 you are eligible to TA CS4 and CS8)