200 likes | 321 Vues
This guide provides a comprehensive introduction to iterators in data structures such as arrays, vectors, linked lists, and trees. It explains the essential methods `hasNext()` and `next()`, alongside implementation strategies, including single iterator classes, custom iterator classes, and nested iterator classes. We discuss the advantages and disadvantages of each implementation type, focusing on performance implications for different data structures. Practical examples demonstrate how to use iterators to efficiently traverse and manipulate elements within data structures, ensuring accuracy in data handling.
E N D
Iterators CS 367 – Introduction to Data Structures
Iterator • Allows a user to step through each item in a data structure • array, vector, linked list, tree, etc. • Two basic components • hasNext() • returns true if the iterator has any more items • next() • returns the next item in the iterator
Example • Print out each item in a vector Vector v = new Vector(); addItems(v); Iterator it = v.iterator(); while(it.hasNext()) System.out.println(it.next().toString());
Iterator hasNext() == true next hasNext() == true next hasNext() == false next
Warning • Note that the next pointer is out-of-bounds after the last call to next() • another call to next() will result in exception • Should always call hasNext() before calling next()
Implementation • Three main ways to implement an iterator • single class for an iterator • requires all data structures to implement an iterator specific interface • create a separate, custom iterator class for each data structure • create a custom iterator class for each data structure and make it an inner class inside the appropriate data structure
Single Iterator Class • Implement a single class called Iterator • Force each data structure that allows iterators to implement an iterator interface interface DSIterator { public int size(); public Object getIndex(int index);
Iterator Class class Iterator { private DSIterator ds; private int nextItem; public Iterator(DSIterator ds) { this.ds = ds; nextItem = 0; } public boolean hasNext() { return nextItem < ds.size(); } public Object next() { Object obj = ds.getIndex(nextItem); nextItem++; return obj; } }
Questions • What happens if user calls next() at end of data? • How many times can user to through iterator? • How does user go through the data again?
Notes on Single Iterator Class • Advantages • only have to write the iterator class once • Disadvantage • performance can suffer greatly for some data structures
Linked List Example class LinkedList implements DSIterator { // start of normal linked list code . . . // end of normal linked list code private int size; // increment (decrement) in add (delete) methods public int size() { return size; } public Object getIndex(int index) { Object tmp = head; for(int i=0; i<index; i++, tmp = tmp.next); return tmp; }
Linked List Example • Notice the problem with the getIndex() method • O(n) performance • Want our iterator to return the next item in O(1) time • Will need a different implementation of the iterator for a list than for a vector
Custom Class • Previous example shows the need for custom iterator classes for different data structures • Custom class will: • take data structure object through constructor • set a pointer to the first data item • define next() method that works in O(1) time
Linked List Implementation class LLIterator { private Node nextItem; public LLIterator(LinkedList list) { nextItem = list.head; } public boolean hasNext() { return nextItem != null; } public Object next() { Object obj = nextItem.data; nextItem = nextItem.next; return obj; } }
Notes on Custom Iterator Classes • Advantage • very good performance • next() is always O(1) • Disadvantage • head of Linked List must be made public • this is a bad thing – why? • have to write a custom iterator for each data type • means the user must know which one to use for which data type
Nested Iterator Class • Java allows one class to be nested inside another • Nest class has full access to private data of main class • can now let iterator access head • head is still kept as a private field
Full Example • Another version of the linked list interface Iterator { public boolean hasNext(); public Object next(); }
class LinkedList { private Node head; // put all the usual stuff here public class LLIterator implements Iterator { private Node nextObject; public LLIterator() { nextObject = head; } } public Iterator iterator() { return new Iterator(); } }
Notes on Nested Class • Advantage • get the same performance as custom class • it still is a custom class • encapsulation remains in tact • head gets to stay private • Disadvantage • custom iterator for each data structure • a bit more confusing to learn and understand
Using Iterators • Assume a nested iterator class public void printContents(Object ds) { Iterator it = ds.iterator(); while(it.hasNext()) System.out.println(it.next().toString()); } • The above code will work with any data structure • of course, it assumes the data structure class supports iterators