1 / 46

Double-Linked Lists and Circular Lists

Double-Linked Lists and Circular Lists. 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

paniz
Download Presentation

Double-Linked Lists and Circular Lists

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CS340 Double-Linked Lists and Circular Lists

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

  3. CS340 Double-Linked Lists (cont.)

  4. CS340 NodeClass private static class Node<E> { private E data; private Node<E> next = null; private Node<E> prev = null; private Node(E dataItem) { data = dataItem; } }

  5. Node Node Node next = = prev data = "Harry" next = null = prev data = "Sam" next = = prev data = "Sharon" Inserting into a Double-Linked List from predecessor sam to predecessor sharon Node<E> sharon = new Node<E>("Sharon"); sharon.next = sam; sharon.prev = sam.prev; sam.prev.next = sharon; sam.prev = sharon;

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

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

  8. CS340 The LinkedListClass and the Iterator, ListIterator, and Iterable Interfaces

  9. CS340 TheLinkedListClass

  10. CS340 The Iterator • A moving place marker • Iteratorobject 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)

  11. CS340 IteratorInterface • Defined in java.util

  12. CS340 IteratorInterface (cont.) • An Iterator is between elements

  13. CS340 IteratorInterface (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 ... }

  14. CS340 Iterators and Removing Elements • remove() deletes the most recent element returned • You must call next()before each remove() • Else IllegalStateExceptionwill 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(); } } }

  16. CS340 ListIteratorInterface • Iteratorlimitations • Traverses Listonly in the forward direction • Provides a removemethod, but no add method • If you do not want to start from the beginning: • You must advance the Iterator using your own loop • Solution: • ListIteratorextends Iterator

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

  18. ListIteratorInterface (cont.)

  19. CS340 ListIteratorInterface (cont.)

  20. CS340 Comparison of IteratorandListIterator • 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 • ListIteratoris required only by the List interface

  21. CS340 Conversion Between ListIteratorand 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?

  22. CS340 Conversion Between ListIteratorand an Index (cont.)

  23. CS340 Implementation of a Double-Linked List Class

  24. CS340 CS340LinkedList

  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. AddMethod • 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 /** Add an item at the specifiedindex. @param index The index at which the object isto be inserted @param obj The object to beinserted @throws IndexOutOfBoundsException if the index is out of range (i < 0 || i > size()) */ public void add(int index, E obj) { listIterator(index).add(obj); }

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

  28. CS340 OtherAddandGetMethods 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; }

  29. CS340 Implementing the ListIteratorInterface • CS340ListIter is an inner class of CS340LinkedListwhich implements the ListIterator interface

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

  31. public CS340ListIter(inti) { 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; } } } Constructor

  32. CS340 ThehasNext()Method • tests to see if nextItem is null public booleanhasnext() { return nextItem != null; }

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

  34. 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(); } }

  35. 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(); }

  36. PreviousMethods 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; }

  37. CS340 TheAddMethod • 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

  38. CS340 Adding to an Empty List Node CS340LinkedList 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

  39. Adding to the Head of the List CS340ListIter nextItem = lastItemReturned = null index = 0 1 Node Node Node next = null = prev data = "Tom" 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++; Node next = null null = prev data = "Ann" newNode

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

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

  42. CS340 Inner Classes: Static and Nonstatic • CS340LinkedListcontains 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’sparent 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

  43. CS340 Circular Lists

  44. 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!

  45. Circular Lists (cont.)

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

More Related