1 Lecture 26 Abstract Data Types –III Overview Creating and manipulating Linked List. Linked List Traversal. Linked List Traversal using Iterator class. Stack Implementation using Linked List. Queue Implementation using Linked List. Recursive List Search. Preview: Introduction to Databases.
2 Lecture 26 Creating and Manipulating a New LinkedList In the last lecture we implemented the List ADT as a Linked List. The following shows how we may use it to create a dynamic list (list that can expand and shrink as required by the application. header LinkedList list = new LinkedList(); list.insert(0,’c’); list.insert(lst.length(),‘a’); c ca list.insert(1,’b’); cba list.remove(0); ba
3 Lecture 26 Linked List Traversal Many common higher level list processing routines require a mechanism to traverse the list. For example: This implementation is very inefficient as each time retrieve(i) is called it starts searching from the start of the list. A common convention is to provide an iterator class which provides methods that can be used to iterate or step through the list. The iterator maintains a record of a current list position. public LinkedList reverseOf(LinkedList list) { LinkedList reverse = new LinkedList(); for(int i=0; i<list.length();i++) { reverse.insert(0,list.retrieve(i)); } return reverse; }
4 Lecture 26 Linked List Iterator Class Some sample methods contained in an iterator class public class LinkedListIterator { private Node cursor;// reference to current position in list public LinkedListIterator(LinkedList list) {// constructor creates iterator from given list cursor = list.getHeader(); } public boolean isPastEnd() { return cursor == null; } public void next() throws NoSuchElementException { if (cursor == null) throw new java.util.NoSuchElementException(); cursor = cursor.getNext(); } public Object retrieve() throws NoSuchElementException { if (cursor == null) throw new java.util.NoSuchElementException(); return cursor.getElement(); }
5 Lecture 26 Using a Linked List Iterator The previous reverseOf method can now be re-implemented using an iterator: This implementation is much more efficient as the iterator maintains a notion of a current position during the list traversal process. public LinkedList reverseOf(LinkedList list) { LinkedList reverse = new LinkedList(); LinkedListIterator iterator = new LinkedListIterator(list); while (!iterator.isPastEnd()) { reverse.insert(0,iterator.retrieve()); // retrieve element at this position iterator.next(); // move to next element in list } return reverse; // return new reversed list }
6 Lecture 26 Stacks and Queues Revisited The original array implementations of Stacks and Queues suffered from inefficiency in that the array was fixed in size. Too small and it was useless, too big and it wasted resources. Both stacks and queues can be implemented more efficiently using linked lists to maintain the stack and queue data. n Stack - push and pop from front of list (Header) n Queue - enQueue at end of list and deQueue from head of list List (Header) (push and pop from here) (dequeue from here) (enqueue here)
7 Lecture 26 Stacks as List Nodes public StackNode { Node top; int size; public Stack() { top = null; } boolean isEmpty() { return top==null; } public void push(Object e) { Node n = new Node(e,top); } public Object peek() { return top.getElement(); } public void pop() { top.setNext(top.getNext()); } A simplistic version using list nodes directly. The next slide discusses the preferred implementation.
8 Lecture 26 public StackList { LinkedList list; public Stack() { list = new LinkedList(); } boolean isEmpty() { return list.isEmpty(); } public void push(Object e) { list.insert(0,e); } public Object peek() { return list.retrieve(0); } public void pop() { list.remove(0); } An ADT such as a Stack requiring flexible data storage can be implemented in terms of a linked list. Note no exception handling code is provided. Implement a Stack Using a Linked List
9 Lecture 26 Implementing a Queue Using LinkedList public QueueList { private LinkedList items; public QueueList() { items = new LinkedList(); } public void enqueue(Object e) { items.insert(items.length(),e); } public void dequeue() { items.remove(0); } public Object front() { return items.retrieve(0); } public boolean isEmpty() { return items.isEmpty(); } public int size() { return items.length(); } The queue implementation is now trivial when using List ADT. One performance issue is with enqueue which calls insert at end of list thus incurring a full list traversal to locate insertion position. Simple solution is to maintain a reference to the tail of the list.
10 Lecture 26 Iterative/Recursive List Search In order to locate the position of an element in a list, the list must be traversed a linear search is performed on the list contents use the LinkedListIterator class to implement the search LinkedListIterator find(Object e, LinkedListIterator iterator) { while (!iterator.isPastEnd()) { if (e.equals(iterator.retrieve())) return iterator; else iterator.next(); } return iterator; } LinkedListIterator find(Object e, LinkedListIterator iterator) { if (iterator.isPastEnd() || e.equals(iterator.retrieve())) return iterator; else { iterator.next(); return find(e, iterator); } Iterative versionRecursive version