Double Linked Lists

Download Report

Transcript Double Linked Lists

CS340
DoubleLinked
Lists and
Circular
Lists
1
CS340
Double-Linked Lists
• Limitations of a singly-linked list:
• Insertion at the front is O(1)
• insertion at other positions is O(n)
• Insertion is convenient only after a referenced node
• Removing a node requires a reference to the previous node
• We can traverse the list only in the forward direction
• How to overcome these limitations?
• Double-linked list
2
CS340
Double-Linked Lists (cont.)
3
CS340
Node Class
private static class Node<E> {
private E data;
private Node<E> next = null;
private Node<E> prev = null;
private Node(E dataItem) {
data = dataItem;
}
}
4
5
Inserting into a Double-Linked List
from predecessor
sam
Node
to predecessor
Node
next =
next = null
= prev
data = "Sam"
= prev
data = "Harry"
sharon
Node<E> sharon = new Node<E>("Sharon");
sharon.next = sam;
Node
sharon.prev = sam.prev;
sam.prev.next = sharon;
next =
sam.prev = sharon;
= prev
data = "Sharon"
6
CS340
Removing from a Double-Linked List
harry
Node
Node
next =
next =
= prev
data = "Dick"
= prev
data = "Sharon"
Node
next =
harry.prev.next = harry.next
harry.next.prev = harry.prev
= prev
data = "Harry"
CS340
A Double-Linked List Class
 A double-linked list object has data fields:
 head (a reference to the first list Node)
 tail (a reference to the last list Node)
 size
 Insertion at either end is O(1)
 Insertion elsewhere is still O(n)
7
CS340
The
LinkedList
Class and
the
Iterator,
ListIterato
r, and
Iterable
Interfaces
8
CS340
The LinkedList Class
9
CS340
10
The Iterator
 A moving place marker
 Iterator object for a list starts at the list head
 It can move by calling its
next method.
 Stays on its current list item until it is needed
Iterator traverses in O(n) while a list traversal
using get() calls in a linked list is O(n2)
 An
CS340
Iterator Interface
• Defined in
java.util
11
CS340
Iterator Interface (cont.)
• An
Iterator is between elements
12
CS340
Iterator Interface (cont.)
 In the following loop, we process all items in
List<Integer>
through an Iterator
Iterator<Integer> iter = aList.iterator();
while (iter.hasNext()) {
int value = iter.next();
// Do something with value
...
}
13
CS340
14
Iterators and Removing Elements
remove() deletes the most recent element returned
 You must call next()before each remove()
 Else
IllegalStateException will be thrown
 LinkedList.remove vs. Iterator.remove:
 LinkedList.remove must walk down the list each time, then
remove, O(n2) complexity
 Iterator.remove removes items without starting over at the
beginning, O(n) complexity
15
CS340
Iterators and Removing Elements
(cont.)
 Remove all elements from a list of type Integer that
are divisible by a particular value:
public static void
removeDivisibleBy(LinkedList<Integer>
aList, int
div) {
Iterator<Integer> iter = aList.iterator();
while (iter.hasNext()) {
int nextInt = iter.next();
if (nextInt % div == 0) {
iter.remove();
}
}
}
CS340
ListIterator Interface
• Iterator limitations
• Traverses List only in the forward direction
• Provides a remove method, but no add method
• If you do not want to start from the beginning:
• You must advance the Iterator using your own loop
• Solution:
• ListIterator extends Iterator
16
CS340
17
ListIterator Interface (cont.)
• ListIterator is positioned between elements of the list
• ListIterator positions: 0 to size
18
ListIterator Interface (cont.)
CS340
ListIterator Interface (cont.)
19
CS340
20
Comparison of Iterator and
ListIterator
• ListIterator is a subinterface of Iterator
• Classes that implement
ListIterator must provide the
features of both
• Iterator:
• Requires fewer methods
• Can iterate over more general data structures
• Iterator is required by the Collection interface
• ListIterator is required only by the List interface
CS340
21
Conversion Between ListIterator
and an Index
• ListIterator:
• nextIndex()returns the index of item to be returned by
next()
• previousIndex() returns the index of item to be returned
by previous()
• LinkedList has method listIterator(int index)
• Returns a ListIterator positioned so next()will return
the item at position index
• How? What is the complexity?
CS340
22
Conversion Between ListIterator
and an Index (cont.)
CS340
Implementation
of a DoubleLinked List Class
23
CS340
CS340LinkedList
24
25
CS340LinkedList (cont.)
import java.util.*;
/** Class CS340LinkedList implements a double linked
list and a ListIterator. */
public class CS340LinkedList <E> {
// Data Fields
private Node <E> head = null;
private Node <E> tail = null;
private int size = 0;
. . .
26
Add Method
Obtain a reference, nodeRef, to /** Add an item at the specified
index.
the node at position index
@param index The index at
2.
Insert a new Node containing
which the object is
obj before the node referenced
to be inserted
by nodeRef
@param obj The object to be
To use a ListIterator object to
inserted
implement add:
@throws
IndexOutOfBoundsException
1. Obtain an iterator that is
if the index is out
positioned just before the Node at
of range
position index
(i < 0 || i > size())
2. Insert a new Node containing obj
*/
before the Node currently
public void add(int index, E obj)
referenced by this iterator
{
1.
listIterator(index).add(obj);
}
CS340
27
Get Method
/** Get the element at
Obtain a reference,
position
nodeRef, to the node at
index.
position index
@param index Position of
item to be
2. Return the contents of
the Node referenced by retrieved
@return The item at index
nodeRef
1.
*/
public E get(int index) {
return
listIterator(index).next();
}
CS340
Other Add and Get Methods
public void addFirst(E item) {
add(0, item);
}
public void addLast(E item) {
add(size, item);
}
public E getFirst() {
return head.data;
}
public E getLast() {
return tail.data;
}
28
CS340
29
Implementing the ListIterator
Interface
• CS340ListIter is an inner class of CS340LinkedList
which implements the ListIterator interface
CS340
Implementing the ListIterator
Interface (cont.)
private class CS340ListIter implements
ListIterator<E> {
private Node <E> nextItem;
private Node <E> lastItemReturned;
private int index = 0;
...
30
31
Constructor
public CS340ListIter(int i) {
if (i < 0 || i > size) { // Validate i parameter.
throw new IndexOutOfBoundsException("Invalid index " + i);
}
lastItemReturned = null; // No item returned yet.
if (i == size) {// Special case of last item
index = size;
nextItem = null;
}
else { // Start at the beginning
nextItem = head;
for (index = 0; index < i; index++) {
nextItem = nextItem.next;
}
}
}
CS340
The hasNext()Method
• tests to see if
nextItem is null
public boolean hasnext() {
return nextItem != null;
}
32
Advancing the Iterator
33
CS340LinkedList
head
tail
size
Node
next
prev
data
3
next
next
null
"Tom"
Node
Node
data
prev
"Harry"
data
prev
"Sam"
CS340ListIter
nextItem
lastItemReturned
index
12
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
lastItemReturned = nextItem;
nextItem = nextItem.next;
index++;
return lastItemReturned.data;
}
CS340
Why is the iterator useful?
• Process all elements of a list
for(i=0; i < aList.size(); i++){
E nextElement = aList.get(i);
}
E get(int index){
Node<E> nodeRef = head;
for(i=0; i < index; i++){
nodeRef = nodeRef.next();
}
}
34
CS340
Why is the iterator useful? (cont.)
• Process all elements of a list
for(i=0; i < aList.size(); i++){
E nextElement = listIterator(i).get();
}
35
36
Previous Methods
public boolean hasPrevious() {
return (nextItem == null && size != 0)
|| nextItem.prev != null;
}
public E previous() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
if (nextItem == null) { // Iterator past the last
element
nextItem = tail;
}
else {
nextItem = nextItem.prev;
}
lastItemReturned = nextItem;
index--;
return lastItemReturned.data;
}
CS340
The Add Method
• 4 cases to address:
• Add to an empty list
• Add to the head of the list
• Add to the tail of the list
• Add to the middle of the list
37
CS340
38
Adding to an Empty List
CS340LinkedList
head = null
tail = null
size = 3
1
Node
next =
null = prev
data = "Tom"
CS340ListIter
nextItem =
lastItemReturned = null
index = 0
1
(after insertion)
if (head == null) {
head = new Node<E>(obj);
tail = head;
}
...
size++
39
CS340ListIter
nextItem =
lastItemReturned = null
index = 0
1
Adding to the Head of the
List
Node
CS340LinkedList
head = null
tail = null
size = 3 4
next =
null = prev
data = "Tom"
Node
newNode
next = null
null = prev
data = "Ann"
Node
next =
= prev
data = "Harry"
Node
next = null
= prev
data = "Sam"
if (nextItem == head) {
Node<E> newNode = new
Node<E>(obj);
newNode.next = nextItem;
nextItem.prev = newNode;
head = newNode;
}
...
size++;
index++;
40
CS340ListIter
nextItem = null
lastItemReturned = null
index = 23
CS340LinkedList
Adding to the Tail of the
List
Node
Node
Node
next =
prev = null
data = "Tom"
next =
= prev
data = "Ann"
next = null
= prev
data = "Sam"
head = null
tail = null
size = 3 4
if (nextItem == null) {
Node<E> newNode = new
Node<E>(obj);
tail.next = newNode;
newNode.prev = tail;
tail = newNode
}
...
size++;
index++;
Node
newNode
next = null
null = prev
data = "Bob"
CS340ListIter
nextItem = null
lastItemReturned = null
index = 12
CS340LinkedList
Adding to the Middle of the
List
Node
Node
Node
next =
prev = null
data = "Tom"
next =
= prev
data = "Ann"
next = null
= prev
data = "Sam"
head = null
tail = null
size = 3 4
else {
Node<E> newNode = new
Node<E>(obj);
newNode.prev = nextItem.prev;
nextItem.prev.next = newNode;
newNode.next = nextItem;
nextItem.prev = newNode;
}
...
size++;
index++;
Node
next = null
null = prev
data = "Bob"
newNode
CS340
42
Inner Classes: Static and Nonstatic
 CS340LinkedList contains two inner classes:
 Node<E> is static: no need for it to access the data fields of its
parent class
 CS340ListIter cannot be declared static because its
methods access and modify data fields of
CS340LinkedList’s parent object which created it
 An inner class which is not static:
 contains an implicit reference to its parent object
 can reference the fields of its parent object
CS340
Circular Lists
43
CS340
44
Circular Lists
 Circular double-linked list:
 Link last node to the first node, and
 Link first node to the last node
 We can also build singly-linked circular lists:
 Traverse in forward direction only
 Advantages:
 Continue to traverse even after passing the first or last node
 Visit all elements from any starting point
 Never fall off the end of a list
 Disadvantage: Code must avoid an infinite loop!
Circular Lists (cont.)
46
CS340
Circular Lists (cont.)
Linked List
Node
head =
tail =
size = 4
next =
= prev
data = “Helen"
Node
Node
next =
= prev
data = “Harry"
next =
= prev
data = “Tom"
Node
next =
= prev
data = "Sharon"