1 Objects that store Objects in a line Linear Collections.
-
Upload
joseph-gray -
Category
Documents
-
view
225 -
download
1
description
Transcript of 1 Objects that store Objects in a line Linear Collections.
1
Objects that store Objects in a line
Linear Collections
What is a Collection? If you don’t know how many objects you’re going to need
to solve a particular problem, you also don’t know how to store those objects. How can you know how much space to create for those objects? You can’t, since that information isn’t known until run time.
A good OOP language comes with a set of collections as part of the package. C++ has the STL Object Pascal has collections in its Visual Component Library
(VCL) Smalltalk Java also has collections in its standard library.
2
Collection Class Hierarchy3
The Collection interface is the root of the collection hierarchy. • A Collection represents a group of objects, known as its elements. • Some Collections allow duplicate elements and others do not. • Some are ordered and others unordered.
This interface is the least common denominator that all collections implement. Collection is used to pass collections around and manipulate them when maximum generality is desired.
Java Collection Class Hierarchy
4
IC
interface
class
abstract classconcrete class
Collection Interface5
Method Summary for Collection<E> boolean add(E e) Ensures that this collection contains the specified element (optional operation). boolean addAll(Collection<? extends E> c) Adds all of the elements in the specified collection to this collection
(optional operation). void clear() Removes all of the elements from this collection (optional operation).
boolean contains(Object o) Returns true if this collection contains the specified element. boolean containsAll(Collection<?> c) Returns true if this collection contains all of the elements in the specified
collection. boolean equals(Object o) Compares the specified object with this collection for equality.
int hashCode() Returns the hash code value for this collection. boolean isEmpty() Returns true if this collection contains no elements.
Iterator<E> iterator() Returns an iterator over the elements in this collection. boolean remove(Object o) Removes a single instance of the specified element from this collection, if it is present
(optional operation). boolean removeAll(Collection<?> c) Removes all of this collection's elements that are also contained in the
specified collection (optional operation). boolean retainAll(Collection<?> c) Retains only the elements in this collection that are contained in the specified
collection (optional operation). int size() Returns the number of elements in this collection.
Object[] toArray() Returns an array containing all of the elements in this collection.
<T> T[] toArray(T[] a) Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the specified array.
Example6
public void example(Collection<String> words) { words.clear(); words.add("A"); words.add("B"); words.add("C"); int s = words.size(); boolean f = words.contains("A"); f = words.contains(words); f = words.remove("D"); f = words.remove("A");}
List Some collections represent a list of
elements A list is ordered (not sorted) A list is dynamic (the size may change) A list is a one-dimensional collection. This
is known as a linear collection. In Java
List is a sub-interface of Collection List introduces index-based methods
7
List Interface8
Method Summary
boolean add(E e) Appends the specified element to the end of this list (optional operation). void add(int index, E element) Inserts the specified element at the specified position in this list (optional operation).
boolean addAll(Collection<? extends E> c) Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's iterator (optional operation).
boolean addAll(int index, Collection<? extends E> c) Inserts all of the elements in the specified collection into this list at the specified position (optional operation).
void clear() Removes all of the elements from this list (optional operation). boolean contains(Object o) Returns true if this list contains the specified element. boolean containsAll(Collection<?> c) Returns true if this list contains all of the elements of the specified collection.
E get(int index) Returns the element at the specified position in this list. int indexOf(Object o) Returns the index of the first occurrence of the specified element in this list, or -1 if this list does
not contain the element. boolean isEmpty() Returns true if this list contains no elements.
Iterator<E> iterator() Returns an iterator over the elements in this list in proper sequence. int lastIndexOf(Object o) Returns the index of the last occurrence of the specified element in this list, or -1 if this list
does not contain the element. E remove(int index) Removes the element at the specified position in this list (optional operation).
boolean remove(Object o) Removes the first occurrence of the specified element from this list, if it is present (optional operation).
boolean removeAll(Collection<?> c) Removes from this list all of its elements that are contained in the specified collection (optional operation).
boolean retainAll(Collection<?> c) Retains only the elements in this list that are contained in the specified collection (optional operation).
E set(int index, E element) Replaces the element at the specified position in this list with the specified element (optional operation).
int size() Returns the number of elements in this list. List<E> subList(int fromIndex, int toIndex) Returns a view of the portion of this list between the specified fromIndex, inclusive,
and toIndex, exclusive.
Lists The List Interface contains many
methods. We must implement these methods to use the List interface.
How could we implement the following methods in a single class? boolean add(E e); boolean remove(E e); void add(int n, E e); E remove(int n);
9
Implementation Choices There are two categories of techniques
for implementing lists. Sequential: Use an array Linked: Use recursive data to link objects
together Each technique has benefits and
advantages There are variations (generally minor) of
each technique
10
Array Based List An array-based implementation will
Use an array to store the data elements The array will not be exposed to clients
11
data:size: 5
ArrayList Object
ArrayList Implementation12
public class ArrayList<E> implements List<E> { private Object data[]; private int size, increment; private static final int DEFAULT_CAPACITY = 250; private static final int DEFAULT_INCREMENT = 250;
public ArrayList(int cap, int incr) { data = new Object[cap]; increment = incr; size = 0; }
public int size() { return size; }
public void add(E obj) { if(size == data.length) { increaseCapacity(); } data[size++] = obj; }
…}
addaddAllclearcontainsisEmptyiteratorremovesize
Iterator An iterator is an object that provides
read access to the elements in a collection
Iterator is an interface containing three methods boolean hasNext() : returns true if the
iteration has more elements E next() : returns the next element in the
interation. Throws a NoSuchElementException if there is no next.
void remove() : removes the last element returned by the iterator (optional).
13
Example Here is a method that uses an iterator to
process the elements of a Collection.
14
public int sum(Collection<Integer> c) { Iterator<Integer> iterator = c.iterator(); int sum = 0; while(iterator.hasNext()) { sum += iterator.next(); }
return sum;}
How to implement an Iterator?public class ArrayList<E> implements List { private Object data[]; private int size, increment; private static final int DEFAULT_CAPACITY = 250; private static final int DEFAULT_INCREMENT = 250;
// increment > 0 and capacity >= 0 public ArrayList(int cap, int incr) { data = new Object[cap]; increment = incr; size = 0; }
public Iterator<E> iterator() { // what goes here? }
// other methods not shown
}
15
How to implement an Iterator?
public class ArrayList<E> implements List { private Object data[]; private int size, increment; private static final int DEFAULT_CAPACITY = 250; private static final int DEFAULT_INCREMENT = 250; public Iterator<E> iterator() { return new ArrayListIterator<E>(); }}
16
public class ArrayListIterator<E> implements Iterator<E> { private Object[] data; private int size, indexOfNext; public ArrayListIterator(int s, Object[] d) { data = d; size = s; }
public boolean hasNext() { return indexOfNext < size; }
public E next() throws NoSuchElementException { return (E)data[indexOfNext++]; }
public void remove() throws UnsupportedOperationException { throw new UnsupportedOperationException(); }}
Stacks Stacks
are a linear collection follow the LIFO principle (last-in first-out)
Metaphors A Pez dispenser. The “last” candy in is the “first” candy
taken out A stack of trays at a cafeteria. The “last” tray place onto
the stack is the “first” one taken off. Applications
The JVM uses a stack to implement function calls (recall “StackOverflowExceptions”)
Determining the best move to make in game theory (depth first searches)
Expression evaluation in compiler theory
17
http://www.flickr.com/photos/tekhne/1470746280/
Stack Basic operations
push(E value) same as ‘add’ Inserts a value onto the top of the stack
E pop() almost the same as ‘remove’ Removes and returns the top of the stack. An error occurs if the stack is empty.
Auxilliary operations int size()
returns the number of elements in the stack E peek()
returns (but doesn’t remove) the top of the stack. An error occurs if the stack is empty.
boolean isEmpty() returns true if the stack is empty and false otherwise
18
Push Pop
Top
ExampleStack<Integer> stack = …;
stack.push(3);stack.push(-5);stack.push(12);stack.push(153);
System.out.println(stack.pop());System.out.println(stack.size());System.out.println(stack.peek());
while(stack.size() > 0) { System.out.println(stack.pop());}
19
Java Collection Class Hierarchy
20
IC
interface
class
abstract classconcrete class
Stack Implementation A stack can be thought of as a list that
has a more constrained interface. add can only mean "add to the top" remove doesn't allow you to specify the
element to be removed. The stack knows which one should be removed.
The same techniques for implementing a list can be leveraged for implementing a stack sequential: use an array linked: use recursive data structures to link
objects
21
Array Based List An array-based implementation will
Use an array to store the data elements The array will not be exposed to clients Adding always acts on the 'top' element
22
data:top: 5
Stack Object
Queue ADT Overview Overview
A linear collection Follows the FIFO principle (first-in first-out)
Metaphors Standing in line at a bank. When you get in line (insertion into
the queue) you stand at the “end” of the line. When you step out of the line (removal from the queue) you are at the “front” of the line.
Applications Print jobs are sent to a “print queue” Events are sent to an “event queue” Useful in “queue theory” which simulates dynamic business
applications
23
Queue ADT Operations Basic operations
enqueue(E value) same as ‘add’ Inserts a value into the tail of the queue.
E dequeue() almost the same as ‘remove’ Removes and returns the head of the queue. An error occurs if the queue is
empty.
Auxilliary operations int size()
returns the number of elements in the queue E peek()
returns (but doesn’t remove) the head of the queue. An error occurs if the queue is empty.
boolean isEmpty() returns true if the queue is empty and false otherwise
24
Enqueue Dequeue
ExampleQueue<Integer> que= new Queue<Integer>();
que.enqueue(3);que.enqueue(-5);que.enqueue(12);que.enqueue(153);
System.out.println(que.dequeue());System.out.println(que.size());System.out.println(que.peek());
while(que.size() > 0) { System.out.println(que.dequeue());}
25
Implementation?26
public class ArrayList<E> implements List<E> { private Object data[]; private int size, increment; private static final int DEFAULT_CAPACITY = 250; private static final int DEFAULT_INCREMENT = 250;
public ArrayList(int cap, int incr) { data = new Object[cap]; increment = incr; size = 0; }
public int size() { return size; }
public void add(E obj) { if(size == data.length) { increaseCapacity(); } data[size++] = obj; }
public E remove(int index) { if(index < 0 || index >= size) throw new NoSuchElementException(); E result = (E)data[index]; for(int i=index; i<size-1; i++){ data[i] = data[i+1]; } data[--size] = null; return result; }
…}
What if we sub-class ArrayList and provide additional methods: enqueue, dequeue, and peek?
DescriptionMethod
Replaces the item at the specified index with the specified objectE set(int index, E element)
Removes and returns the element at the specified indexObject remove(int index)
Returns the index of the first occurenc of this object in the listint indexOf(E element)
Returns the element at the specified indexObject get(int index)
Inserts all of the elements in the specified collection into this list at the specified position.boolean addAll(int index, Collection c)
Inserts the specified element at the specified position in this listvoid add(int index, E element)
Queue Implementations Sequential Implementation (using “circular” arrays):
Use an array but imagine it as a “circular” array. Has a fixed capacity (unless some type of “resize” method is implemented) Enqueuing is performed at the “last” index. Dequeuing is performed at the “first” index.
27
first last
index 0
index 11
index 0 index 11
first last
Stack Example28
Problem: Determine if a given mathematical expression is parenthetically balanced. Expressions are parenthetically balanced if each left-parenthesis is closed after all enclosed parenthetic expressions have been closed and no unmatched parenthesis remain.Examples:
(3 + 4 * (5/2))(3 + 8) * 5/2)(3 + (8 * ( 4 – 2))
algorithm boolean isBalanced(String exp) INPUT: A string containing vals, ids, ops and parens OUTPUT: True if the expression is parenthetically balanced and false otherwise
Let S be a stack for every token t in exp (scanning from left to right) if t is a left-parenthesis then S.push(t) else if t is a right-parenthesis then if S.pop() is not a left-parenthesis then return false return S.isEmpty()
Stack Example Let’s define a mathematical expression
(ME) A number is a ME A variable (identifier) is a ME If X and Y are ME’s then so is
X + Y X – Y X * Y X / Y
If X is a ME then so is (X)
29
Are the following ME’s? (x + 3 * 5) * (3 / 1) (x * 3)(y + 2) 3 * 2 + (2/4)*5
Stack Example30
Problem: Determine if a string represents a mathematical expression.
algorithm boolean isExpression(String exp) INPUT: A string OUTPUT: True if the input is an ME and false otherwise
Let S be a stack for every token t in exp (scanning from left to right) if t is a left-parenthesis S.push(t) else if t is a number or identifier and s.peek() is an operator S.pop(); S.pop(); S.push(EXP); else if t is a number or identifer S.push(EXP) else if t is a right-parenthesis then if S.pop() is not EXP then return false if S.pop() is not a left-parenthesis then return false S.push(EXP) return S.pop() == EXP && S.isEmpty()
Stack ExampleParenthesis balancing is incorporated into most text editors and HTML verification programs.
HTML documents consist of tagged items. Tags must be properly nested (or balanced). The parenthesis balancing algorithm can be easily extended to check that HTML tags are properly balanced
31
<html> <head><title>Simple HTML File</title></head> <body> <b>Some text goes here</b> <table> <tr><td>One</td><td>Two</td></tr> </table> </body> </html>
Expression ExampleFully parenthesized expressions have parenthesis surrounding each infix expression. For example (((3.1 + 1.0) * 5.0) / 12.3) is fully parenthesized while the expression ((3.1 + 12) - 18) + 6 is not.
Write an algorithm to evaluate a fully parenthesized expression.
32
algorithm evaluate(exp) INPUT: A fully parenthesized expression OUTPUT: A number that is the result of evaluating the input expression
Let S be a stack for every token t in exp (scanning left to right) if t is a number or operator S.push(t) else if t is a right paren y = S.pop() op = S.pop() x = S.pop() S.push(x op y) if S.size() is equal to 1 return S.pop() else an error occurs
Expression ExampleA postfix expression is an expression where the operator always follows the operands. For example 3 5 + evaluates to 8 and is written in postfix form.
33
algorithm evaluate(exp) INPUT: A String exp that is a postfix expression OUTPUT: A number that is the result of evaluating the input expression
Let S be a stack for every token t in exp (scanning left to right) if t is a number S.push(t) else x = S.pop() y = S.pop() S.push(y t x) // apply operation t to operands y and x
if S.size() is equal to 1 return S.pop() else an error occurs
3 5 2 6 + 10 5 - - *
Expression ExampleInfix expressions are where the operator occurs between the operands. This is the kind of representation for mathematical expressions that we are accustomed to.
34
algorithm infixToPostfix(exp) INPUT: A String exp that is a postfix expression OUTPUT: A postfix expression that is equivalent to the infix input
Let S be a stack for every token t in exp (scanning left to right) if t is a left-paren S.push(t) else if t is a number print t else if t is an operator print S.pop() until one of the following occurs 1) The stack S becomes empty 2) S.top() is a left paren 3) S.top() has a lower precedence than the current operator when one of these 3 things occurs then S.push(t) else if t is a right-paren print S.pop() until S.top() is a left-paren S.pop() and ignore the left-paren print S.pop() until the stack S is empty
List Implementation Singly-Linked Implementation:
Uses a recursively-defined “list node” structure Imposes a linear structure on otherwise unrelated elements Stores data elements
Has dynamic capacity with little “wasted” memory Keep track of the “head” node from which all other nodes can be
accessed “Natural” operations are from the front since they are “fast”
35
Next
Value
Next
Value
Next
Value
Head Node
List Implementation Doubly-Linked Implementation:
Uses a recursively-defined “list node” structure to hold data elements Has dynamic capacity with little “wasted” memory Keep track of the “head” and “tail” nodes and can access all other
nodes “Natural” operations are from the head and tail since they are “fast”
36
NextPrev
Head
Value
NextPrev
Value
NextPrev
Value
Tail
SinglyLinkedListNode37 public class SinglyLinkedListNode<E> {
private E value; private SinglyLinkedListNode<E> next;
public SinglyLinkedListNode(E value, SinglyLinkedListNode<E> next) { setNext(next); setValue(value); }
public SinglyLinkedListNode(E value) { this(value, null); }
public E getValue() { return value; }
public SinglyLinkedListNode<E> getNext() { return next; }
public void setNext(SinglyLinkedListNode<E> next) { this.next = next; }
public void setValue(E value) { this.value = value; }}
SinglyLinkedList Write a class that implements List.
Name it SinglyLinkedListNoSentinal Use a single instance variable
Name the variable ‘head’ Of type SinglyLinkedListNode<E>
38
public class SinglyLinkedListNoSentinal<E> implements List<E> { private SinglyLinkedListNode<E> head;
public SinglyLinkedListNoSentinal() { // what goes here? }
public void add(E e) { // what goes here? } …}
Java ListIteratorAllows the programmer to traverse the list in either direction, modify the list during iteration, and obtain the iterator's current position in the list.
A ListIterator has no current element; its cursor position always lies between the element that would be returned by a call to previous() and the element that would be returned by a call to next(). In a list of length n, there are n+1 valid index values, from 0 to n, inclusive.
(taken from the Java 1.4 API documentation)
39
ListIterator Interface40
public interface ListIterator extends Iterator {public void add(Object v);public boolean hasPrevious();public int nextIndex();public Object previous();public int previousIndex();public void set(Object v);
}
public interface Iterator {public boolean hasNext();public Object next();public void remove(); // optional operation!
}
ListIterator Documentation
Stack Implementations Linked Implementation:
Use a list. Has a dynamic capacity Push/Pop by adding/removing from the beginning/end of the
list
41
Next
Data
Next
Data
Next
Data
Head Node
Queue Implementations Linked implementation
Use a list. Has a dynamic capacity Enqueuing is performed at the head. Dequeuing is performed at the tail
42
Next
Prev
Head Node
Data
Next
Prev
Data
Next
Prev
Data
Tail Node
Performance43
– Questions to ponder:– Which implementation has the best runtime performance?– Which implementation has the best memory usage?– Which implementation is easier to code?
O(1)O(1)sizeO(1)O(1)topO(1)O(1)isEmptyO(1)O(1)dequeueO(1)O(1)enqueue
LinkedSequentialMethod
Summary Linear data structures are linearly ordered
collections of objects. Design and implementation issues of the following ADTs where covered: Lists Stacks Queues
Detailed examples of Polynomials Radix sort Parenthesis balancing Expression evaluation
44
Is the semester over yet?