# Double-Linked Lists and Circular Lists

## Presentation on theme: "Double-Linked Lists and Circular Lists"— Presentation transcript:

CS340 Double-Linked Lists and Circular Lists

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

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; }

from predecessor sam next = = prev data = "Harry" Node next = null = prev data = "Sam" Node to predecessor sharon Node<E> sharon = new Node<E>("Sharon"); sharon.next = sam; sharon.prev = sam.prev; sam.prev.next = sharon; sam.prev = sharon; next = = prev data = "Sharon" Node

CS340 Removing from a Double-Linked List harry next = = prev data = "Dick" Node next = = prev data = "Sharon" Node next = = prev data = "Harry" Node harry.prev.next = harry.next harry.next.prev = harry.prev

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)

CS340 The LinkedList Class and the Iterator, ListIterator, and Iterable Interfaces

The Iterator Iterator object for a list starts at the list head
CS340 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 An Iterator traverses in O(n) while a list traversal using get() calls in a linked list is O(n2)

Iterator Interface Defined in java.util CS340
The List interface declares the method iterator which returns an Iterator object that iterates over the elements of that list

Iterator Interface (cont.)
CS340 Iterator Interface (cont.) An Iterator is between elements

Iterator Interface (cont.)
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 ... }

Iterators and Removing Elements
CS340 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 Explain to your neighbor why these complexities

Iterators and Removing Elements (cont.)
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(); }

ListIterator Interface
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

ListIterator Interface (cont.)
CS340 ListIterator Interface (cont.) ListIterator is positioned between elements of the list ListIterator positions: 0 to size

ListIterator Interface (cont.)

ListIterator Interface (cont.)
CS340 ListIterator Interface (cont.) Which one is more general? Convince your neighbor

Comparison of Iterator and ListIterator
CS340 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

Conversion Between ListIterator and an Index
CS340 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? The listIterator (int index) method creates a new ListIterator that starts at the beginning, and walks down the list to the desired position – generally an O(n) operation

Conversion Between ListIterator and an Index (cont.)
CS340 Conversion Between ListIterator and an Index (cont.) The listIterator (int index) method creates a new ListIterator that starts at the beginning, and walks down the list to the desired position – generally an O(n) operation

Implementation of a Double-Linked List Class
CS340 Implementation of a Double-Linked List Class

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; . . .

Add Method Obtain a reference, nodeRef, to the node at position index
/** Add an item at the specified index The index at which the object is to be obj The object to be IndexOutOfBoundsException if the index is out of range (i < 0 || i > size()) */ public void add(int index, E obj) { listIterator(index).add(obj); } Obtain a reference, nodeRef, to the node at position index Insert a new Node containing obj before the node referenced by nodeRef To use a ListIterator object to implement add: Obtain an iterator that is positioned just before the Node at position index Insert a new Node containing obj before the Node currently referenced by this iterator It is not necessary to declare a local ListIterator; the method call listIterator returns an anonymous ListIterator object

Get Method Obtain a reference, nodeRef, to the node at position index
CS340 Get Method /** Get the element at position index Position of item to be The item at index */ public E get(int index) { return listIterator(index).next(); } Obtain a reference, nodeRef, to the node at position index Return the contents of the Node referenced by nodeRef

Implementing the ListIterator Interface
CS340 Implementing the ListIterator Interface CS340ListIter is an inner class of CS340LinkedList which implements the ListIterator interface

Implementing the ListIterator Interface (cont.)
CS340 Implementing the ListIterator Interface (cont.) private class CS340ListIter implements ListIterator<E> { private Node <E> nextItem; private Node <E> lastItemReturned; private int index = 0; ...

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;

The hasNext()Method tests to see if nextItem is null
CS340 The hasNext()Method tests to see if nextItem is null public boolean hasnext() { return nextItem != null; }

CS340LinkedList head tail size 3 next prev null data "Tom" Node next prev Node next prev data "Sam" Node data "Harry" CS340ListIter nextItem lastItemReturned index 1 public E next() { if (!hasNext()) { throw new NoSuchElementException(); } lastItemReturned = nextItem; nextItem = nextItem.next; index++; return lastItemReturned.data; 2

Why is the iterator useful?
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();

Why is the iterator useful? (cont.)
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(); }

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;

Adding to an Empty List (after insertion) if (head == null) {
CS340 Adding to an Empty List CS340LinkedList Node next = null = prev data = "Tom" head = null tail = null size = 3 (after insertion) 1 if (head == null) { head = new Node<E>(obj); tail = head; } ... size++ CS340ListIter nextItem = lastItemReturned = null index = 0 1

CS340ListIter nextItem = lastItemReturned = null index = 0 1 Node next = null = prev data = "Tom" Node Node next = null = prev data = "Sam" next = = prev data = "Harry" CS340LinkedList head = null tail = null size = 3 4 if (nextItem == head) { Node<E> newNode = new Node<E>(obj); newNode.next = nextItem; nextItem.prev = newNode; head = newNode; } ... size++; index++; next = null null = prev data = "Ann" Node newNode

Adding to the Tail of the List
CS340ListIter nextItem = null lastItemReturned = null index = 2 Node next = prev = null data = "Tom" Node Node next = null = prev data = "Sam" 3 next = = prev data = "Ann" CS340LinkedList 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++; next = null null = prev data = "Bob" Node newNode

Adding to the Middle of the List
CS340ListIter nextItem = null lastItemReturned = null index = 1 Node next = prev = null data = "Tom" Node Node next = null = prev data = "Sam" 2 next = = prev data = "Ann" CS340LinkedList head = null tail = null size = 3 4 next = null null = prev data = "Bob" Node newNode else { Node<E> newNode = new Node<E>(obj); newNode.prev = nextItem.prev; nextItem.prev.next = newNode; newNode.next = nextItem; nextItem.prev = newNode; } ... size++; index++;

Inner Classes: Static and Nonstatic
CS340 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 Since its parent class is already defined with the parament <E>, KWListIter cannot be declared as KWListIter<E>; if it were, an incompatible types syntax error would occur

CS340 Circular Lists

CS340 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.)

Circular Lists (cont.) Linked List Node head = tail = size = 4 next =
CS340 Circular Lists (cont.) head = tail = size = 4 Linked List next = = prev data = “Helen" Node next = = prev data = “Harry" Node next = = prev data = “Tom" Node next = = prev data = "Sharon" Node