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"