Algorithms Data Structures M 8 List and Iterator

  • Slides: 48
Download presentation
Algorithms & Data Structures (M) 8 List and Iterator ADTs § List concepts §

Algorithms & Data Structures (M) 8 List and Iterator ADTs § List concepts § List applications § A list ADT: requirements, contract § Iterators § Implementations of lists: using arrays and linked-lists § Lists in the Java class library © 2008 David A Watt, University of Glasgow

List concepts (1) § A list is a sequence of elements, in a fixed

List concepts (1) § A list is a sequence of elements, in a fixed order. Elements can added/removed at any position. § Elements are in positions 0 (leftmost), 1, 2, …. § The size (or length) of a list is the number of elements. § The concatenation of lists l 1 and l 2 is a list containing all elements of l 1 followed by all elements of l 2. § We can traverse a list (or iterate over the list), i. e. , visit each of the list’s elements in turn. 8 -2

List concepts (2) § Mathematical notation for lists: – «x 0, x 1, …,

List concepts (2) § Mathematical notation for lists: – «x 0, x 1, …, xn– 1» is a list of length n, whose elements are x 0, x 1, …, xn– 1 (in that order). – « » is the empty list. – Note: We can use this notation in algorithms, but it is not supported by Java. 8 -3

Example: lists and concatenation § A list of integers: fibonacci = « 1, 1,

Example: lists and concatenation § A list of integers: fibonacci = « 1, 1, 2, 3, 5, 8, 13, 21, 34» § A list of airports: tour = «GLA, LHR, CDG, GLA» § Lists of words: hamlet 1 = «‘to’, ‘be’, ‘or’, ‘not’, ‘to’, ‘be’» hamlet 2 = «‘that’, ‘is’, ‘the’, ‘question’» § Concatenation of those lists of words: «‘to’, ‘be’, ‘or’, ‘not’, ‘to’, ‘be’, ‘that’, ‘is’, ‘the’, ‘question’» 8 -4

Lists vs linked-lists § Do not confuse the list abstract data type with linked-list

Lists vs linked-lists § Do not confuse the list abstract data type with linked-list data structures. § A list ADT can be implemented using different data structures (arrays, linked-lists). § Conversely, linked-list data structures can be used to implement many different ADTs (e. g. , stacks, queues, lists, sets). 8 -5

List applications § A sentence is a list of words. – The words are

List applications § A sentence is a list of words. – The words are in the order they are read or spoken. § An itinerary is a list of places visited on a tour. – The places are in the order they are visited. § A log is a list of event records (e. g. , equipment faults). – The event records are in time order. 8 -6

Example: simple text editor (1) § Consider a very simple text editor that supports

Example: simple text editor (1) § Consider a very simple text editor that supports insertion and deletion of complete lines only. § The user can load text from a file, or save the text to a file. § The user can select any line of the text: – directly (by pointing at it, or giving a line number) – by searching for a line matching a given search string. § The user can delete the selected line. § The user can insert a new line, either above the selected line or below the selected line. 8 -7

Example: simple text editor (2) § We can represent the text being edited by:

Example: simple text editor (2) § We can represent the text being edited by: – a list of lines, text – the position sel of the selected line § We can implement the user commands straightforwardly in terms of list operations, e. g. : – Delete: remove the line at position sel in text. – Insert above: add the new line at position sel in text, then increment sel. – Insert below: increment sel, then add the new line at position sel in text. – Save: traverse text, writing each line to the output file. 8 -8

List ADT: requirements § Requirements: 1) It must be possible to make a list

List ADT: requirements § Requirements: 1) It must be possible to make a list empty. 2) It must be possible to test whether a list is empty. 3) It must be possible to obtain the length of a list. 4) It must be possible to add an element at any position in a list. 5) It must be possible to remove the element at any position in a list. 6) It must be possible to inspect or update the element at any position in a list. 7) It must be possible to concatenate lists. 8) It must be possible to test lists for equality. 9) It must be possible to traverse a list. 8 -9

List ADT: contract (1) § Possible contract for homogeneous lists: public interface List<E> {

List ADT: contract (1) § Possible contract for homogeneous lists: public interface List<E> { // Each List<E> object is a homogeneous list // whose elements are of type E. ////// Accessors ////// public boolean is. Empty (); // Return true if and only if this list is empty. public int size (); // Return this list’s length. 8 -10

List ADT: contract (2) § Possible contract (continued): public E get (int p); //

List ADT: contract (2) § Possible contract (continued): public E get (int p); // Return the element at position p in this list. public boolean equals (List<E> that); // Return true if and only if this list and that have the // same length, and each element of this list equals // the corresponding element of that. 8 -11

List ADT: contract (3) § Possible contract (continued): ////// Transformers ////// public void clear

List ADT: contract (3) § Possible contract (continued): ////// Transformers ////// public void clear (); // Make this list empty. public void set (int p, E it); // Replace the element at position p in // this list by it. public void add (int p, E it); // Add it at position p in this list. public void add. Last (E it); // Add it after the last element of this list. This changes the positions of succeeding elements. 8 -12

List ADT: contract (4) § Possible contract (continued): public void add. All (List<E> that);

List ADT: contract (4) § Possible contract (continued): public void add. All (List<E> that); // Add all the elements of that after the // last element of this list. public E remove (int p); // Remove and return the element at // position p in this list. This changes the positions of succeeding elements. ////// Iterator ////// public Iterator<E> iterator (); // Return an iterator that will visit all // elements of this list, in left-to-right order. } 8 -13

Traversal (1) § To traverse array: for (int i = 0; i < array.

Traversal (1) § To traverse array: for (int i = 0; i < array. length; i++) … array[i] … This traversal has time complexity O(n). § We could mimic this to traverse list: for (int p = 0; p < list. size(); p++) … list. get(p) … … list. set(p, x) … § But this traversal could have time complexity O(n 2), if get and set turn out to be O(n). 8 -14

Traversal (2) § Better, use an iterator to traverse list: Iterator<T> elements = list.

Traversal (2) § Better, use an iterator to traverse list: Iterator<T> elements = list. iterator(); while (elements. has. Next()) { T elem = elements. next(); … elem … } visits the next constructs an iterator over the elements of list tests whether that iterator still has more elements to visit element in that iterator § This traversal has time complexity O(n), since the has. Next() and next() operations are guaranteed to be O(1). 8 -15

Iterators (1) § View an iterator as a path along which we visit the

Iterators (1) § View an iterator as a path along which we visit the elements one by one, in some desired order. § Examples of iterators over a list: « ‘to’, ‘be’, ‘or’, ‘not’, ‘to’, ‘be’ » left-to-right iterator right-to-left iterator 8 -16

Iterators (2) § The List interface’s iterator() operation constructs a left-to-right iterator over the

Iterators (2) § The List interface’s iterator() operation constructs a left-to-right iterator over the list elements. § The iterator’s has. Next() operation tests whethere is a next element still to be visited. § The iterator’s next() operation returns the next element (if any). 8 -17

Iterator ADT: contract § Java’s contract for iterators: public interface Iterator<E> { // Each

Iterator ADT: contract § Java’s contract for iterators: public interface Iterator<E> { // Each Iterator<E> object represents an iterator // over some collection of elements of type E. public boolean has. Next (); // Return true if and only if this iterator has a next // element. Guaranteed O(1). public E next (); // Return the next element in this iterator. // Guaranteed O(1). … omitted operation } 8 -18

Iterators: implementation § An iterator is represented by a position on the iterator’s path,

Iterators: implementation § An iterator is represented by a position on the iterator’s path, typically: – an index (if the elements are held in an array) – a link (if the elements are held in a linked-list). § The has. Next() operation tests whethere is a next position on the iterator’s path. § The next() operation advances to the next position on the iterator’s path, and returns the element at that position. – It throws an exception if there is no next position. 8 -19

Implementation of lists using arrays (1) § Represent a bounded list (size cap) by:

Implementation of lists using arrays (1) § Represent a bounded list (size cap) by: – a variable size – an array elems of length cap, containing the elements in elems[0…size– 1]. last element first element Invariant: Empty list: Illustration (cap = 6): 0 1 unoccupied size– 1 element cap– 1 element size=0 0 GLA cap– 1 1 LHR 2 CDG 3 size=4 GLA 5 8 -20

Implementation of lists using arrays (2) § Java implementation: public class Array. List<E> implements

Implementation of lists using arrays (2) § Java implementation: public class Array. List<E> implements List<E> { private E[] elems; private int size; ////// Constructor ////// public Array. List (int cap) { elems = (E[]) new Object[cap]; size = 0; } 8 -21

Implementation of lists using arrays (3) § Java implementation (continued): ////// Accessors ////// public

Implementation of lists using arrays (3) § Java implementation (continued): ////// Accessors ////// public int size () { return size; } public E get (int p) { if (p < 0 || p >= size) throw …; return elems[p]; } … 8 -22

Implementation of lists using arrays (4) § Java implementation (continued): ////// Transformers ////// public

Implementation of lists using arrays (4) § Java implementation (continued): ////// Transformers ////// public void add (int p, E it) { if (p < 0 || p > size) throw …; if (size == elems. length) … for (int j = size; j > p; j--) elems[j] = elems[j-1]; elems[p] = it; size++; } … 8 -23

Implementation of lists using arrays (5) § Java implementation (continued): ////// Iterator ////// public

Implementation of lists using arrays (5) § Java implementation (continued): ////// Iterator ////// public Iterator<E> iterator () { return new LRIterator(); } ////// Inner class ////// private class LRIterator implements Iterator<E> { … } } 8 -24

Implementation of lists using arrays (6) § Implementing iterators over Array. List objects: //////

Implementation of lists using arrays (6) § Implementing iterators over Array. List objects: ////// Inner class ////// private class LRIterator implements Iterator<E> { // An LRIterator object is a left-to-right iterator // over an Array. List<E> object. private int position; // position is the index of the slot containing the // next element to be visited. private LRIterator () { position = 0; } 8 -25

Implementation of lists using arrays (7) § Implementing iterators over Array. List objects (continued):

Implementation of lists using arrays (7) § Implementing iterators over Array. List objects (continued): public boolean has. Next () { return (position < size); } public E next () { if (position >= size) throw …; return elems[position++]; } … } 8 -26

Implementation of lists using arrays (8) § Since LRIterator is a non-static inner class

Implementation of lists using arrays (8) § Since LRIterator is a non-static inner class of Array. List, its instance methods can access Array. List instance variables. E. g. : tour class elems Array. List size 4 class length Object[ ] 6 class iter LRIterator 0 GLA position 0 1 LHR 2 CDG 3 GLA 4 5 iterator constructed by iter = tour. iterator(); 8 -27

Implementation of lists using SLLs (1) § Represent an (unbounded) list by: – a

Implementation of lists using SLLs (1) § Represent an (unbounded) list by: – a variable size – an SLL, with links to both first and last nodes. first element first Invariant: last size element last element first Empty list: last size 0 first Illustration: last size 4 GLA LHR CDG GLA 8 -28

Implementation of lists using SLLs (2) § Java implementation: public class Linked. List<E> implements

Implementation of lists using SLLs (2) § Java implementation: public class Linked. List<E> implements List<E> { private Node first, last; private int size; ////// Inner class ////// private static class Node { … } ////// Constructor ////// public Linked. List () { first = last = null; size = 0; } 8 -29

Implementation of lists using SLLs (3) § Java implementation (continued): ////// Accessors ////// public

Implementation of lists using SLLs (3) § Java implementation (continued): ////// Accessors ////// public int size () { return size; } public E get (int p) { if (p < 0 || p >= size) throw …; return locate(p). element; } … 8 -30

Implementation of lists using SLLs (4) § Java implementation (continued): ////// Auxiliary method //////

Implementation of lists using SLLs (4) § Java implementation (continued): ////// Auxiliary method ////// private Node locate (int p) { // Return a link to the node at position p in this list. Node curr = first; for (int j = 0; j < p; j++) curr = curr. succ; return curr; } 8 -31

Implementation of lists using SLLs (5) § Java implementation (continued): ////// Transformers ////// public

Implementation of lists using SLLs (5) § Java implementation (continued): ////// Transformers ////// public void add (int p, E it) { if (p < 0 || p > size) throw …; Node newest = new Node(it, null); if (p == 0) { newest. succ = first; first = newest; } else { Node pred = locate(p-1); newest. succ = pred. succ; pred. succ = newest; } if (newest. succ == null) last = newest; size++; } 8 -32

Implementation of lists using SLLs (6) § Java implementation (continued): ////// Iterator ////// public

Implementation of lists using SLLs (6) § Java implementation (continued): ////// Iterator ////// public Iterator<E> iterator () { return new LRIterator(); } ////// Inner class ////// private class LRIterator implements Iterator<E> { … } } 8 -33

Implementation of lists using SLLs (7) § Implementing iterators over Linked. List objects: private

Implementation of lists using SLLs (7) § Implementing iterators over Linked. List objects: private class LRIterator implements Iterator<E> { // An LRIterator object is a left-to-right iterator over // a Linked. List<E> object. private Node position; // position is a link to the node containing the next // element to be visited. private LRIterator () { position = first; } 8 -34

Implementation of lists using SLLs (8) § Implementing iterators over Linked. List objects (continued):

Implementation of lists using SLLs (8) § Implementing iterators over Linked. List objects (continued): public boolean has. Next () { return (position != null); } public E next () { if (position == null) throw …; E next. Elem = position. element; position = position. succ; return next. Elem; } … } 8 -35

Implementation of lists using SLLs (9) § Since LRIterator is a non-static inner class

Implementation of lists using SLLs (9) § Since LRIterator is a non-static inner class of Linked. List, its instance methods can access Linked. List instance variables: class tour first last Linked. List class element succ Node GLA class iter LRIterator size 4 class element succ Node GLA position iterator constructed by iter = tour. iterator(); 8 -36

Summary of list implementations § Time complexities of main operations: Operation Array representation SLL

Summary of list implementations § Time complexities of main operations: Operation Array representation SLL representation get O(1) O(p) set O(1) O(p) remove O(n) O(p) add O(n) O(p) O(1) O(n) O(1) equals O(n) add. All O(n') add. Last best worst where n' = size of second list 8 -37

Iterating over a list with a Java for-loop § The following code pattern is

Iterating over a list with a Java for-loop § The following code pattern is extremely common: List<T> list; … Iterator<T> elems = list. iterator(); while (elems. has. Next()) { T elem = elems. next(); … elem … } § So Java provides equivalent for-loop notation: List<T> list; … for (T elem : list) { … elem … } Read this as “for each element elem in list, do the following”. 8 -38

Lists in the Java class library (1) § The library interface java. util. List<E>

Lists in the Java class library (1) § The library interface java. util. List<E> is similar to the above interface List<E>. § The library class java. util. Array. List<E> implements java. util. List<E>, representing each list by an array. § The library class java. util. Linked. List<E> implements java. util. List<E>, representing each list by a doubly-linked-list. (Why? ) 8 -39

Lists in the Java class library (2) § Time complexities of the principal list

Lists in the Java class library (2) § Time complexities of the principal list methods: Array. List Linked. List get O(1) O(p) set O(1) O(p) remove O(n) O(p) add O(n) O(p) O(1) O(n) O(1) ditto Method add. Last best worst amortized 8 -40

Aside: amortized complexity (1) § An operation’s amortized time complexity reflects its performance averaged

Aside: amortized complexity (1) § An operation’s amortized time complexity reflects its performance averaged over a large number of calls. § Consider the add. Last method in Array. List : – Normally, only 1 copy is needed. – When the array is full, n elements are copied into a new array with doubled length, so in total n+1 copies are needed. 8 -41

Aside: amortized complexity (2) total 60 copies § Consider 30 consecutive additions to an

Aside: amortized complexity (2) total 60 copies § Consider 30 consecutive additions to an empty list (with initial capacity 4). 50 40 § Number of copies: 1, 1, 5, 1, 1, 1, 9, 1, 1, 1, 17, 1, 1, 1, 1 (total 58) § On average: 2 copies per call. § Amortized time complexity is O(1). 30 20 10 0 0 10 20 30 no. of calls 8 -42

Example: simple text editor again (1) § Outline implementation of the simple text editor:

Example: simple text editor again (1) § Outline implementation of the simple text editor: public class Text. Editor { private List<String> text; private int sel; // position of the selected line public Text. Editor () { // Make the text empty. text = new Array. List<String>(); sel = -1; or: } new Linked. List<String>() 8 -43

Example: simple text editor again (2) § Outline implementation (continued): public void select (int

Example: simple text editor again (2) § Outline implementation (continued): public void select (int p) { // Select the line at position p. if (p < 0 || p >= text. size()) throw …; sel = p; } public void delete () { // Delete the selected line. if (sel < 0) throw …; text. remove(sel); if (sel == text. size()) sel--; } 8 -44

Example: simple text editor again (3) § Outline implementation (continued): public void find (String

Example: simple text editor again (3) § Outline implementation (continued): public void find (String str) { // Select the next line containing str as a substring. // Wrap round to line 0 if necessary. if (sel < 0) throw …; int p = sel, n = text. size(); do { String line = text. get(p); if (line. index. Of(str) >= 0) { // … str found sel = p; return; } if (++p == n) p = 0; } while (p != sel); throw …; // str not found } 8 -45

Example: simple text editor again (4) § Outline implementation (continued): public void insert. Above

Example: simple text editor again (4) § Outline implementation (continued): public void insert. Above (String line) { // Insert line immediately above the selected line. if (sel < 0) throw …; text. add(sel, line); sel++; } public void insert. Below (String line) { // Insert line immediately below the selected line. sel++; text. add(sel, line); } 8 -46

Example: simple text editor again (5) § Outline implementation (continued): public void load (Buffered.

Example: simple text editor again (5) § Outline implementation (continued): public void load (Buffered. Reader input) { // Load the entire contents of input into the text. for (; ; ) { String line = input. read. Line(); if (line == null) break; text. add. Last(line); } sel = text. size() - 1; // select last line } 8 -47

Example: simple text editor again (6) § Outline implementation (continued): public void save (Buffered.

Example: simple text editor again (6) § Outline implementation (continued): public void save (Buffered. Writer output) { // Save the text to output. for (String line : text) output. write(line + "n"); } } 8 -48