Click presentation screen icon to the right to see the slide show.
Data structures built for particular, common, patterns of accessing elements.
From the user's side of the wall, how do you want to use a stack?
That's it. Prevent user from seeing or removing any other items. Always add, examine, and remove from the “top” of the stack.
Stack<String> stack = new Stack<String>();
To add is to “push” onto the top of the stack.
stack.push("something");
stack.push("hello");
To examine is to “peek” at the top of the stack.
String top = stack.peek(); // top is "hello"
To remove is to “pop” from the top of the stack.
String top = stack.pop(); // top is now "hello" String top = stack.pop(); // top is now "something"
To see if it is empty,
boolean empty = stack.isEmpty();
An axiom of a stack is, a push followed by a pop does not change the stack.
stack.push(newItem).pop() = stack
Let's formalize our view of the Stack using a java interface.
public interface StackInterface { ... What goes in here? ... }
Let's formalize our view of the Stack using a java interface.
public interface StackInterface { ... What goes in here? ... ... Right. Only constants and abstract methods. ... }
public interface StackInterface<T> { public boolean isEmpty(); public void push(T newItem) throws StackException; public T pop() throws StackException; public T peek() throws StackException; }
But with all of those wonderful comments on pages 363-364 which include preconditions and postconditions.
Don't forget to define the new exception class.
public class StackException extends java.lang.RuntimeException { public StackException(String s) { super(s); } }
First, let's create a stack. Let's say it will hold integers.
Stack<Integer> stack = new Stack<Integer>();
public class Stack<T> implements StackInterface<T> { Node<T> top; int size; public Stack() { top = null; size = 0; } }
Now, try pushing something on the stack.
stack.push(42);
How would you implement this?
public class Stack<T> implements StackInterface<T> { . . . public void push(T newItem) { Node<T> newNode = new Node<T>(newItem, top); top = newNode; size++; } }
Now, what if we push again?
stack.push(62);
What will the linked list look like?
And now, pop the top.
int top = stack.pop();
What will the list look like?
And now, pop the top.
int top = stack.pop();
What will the list look like?
And how would you implement it?
And now, pop the top.
int top = stack.pop();
What will the list look like?
And how would you implement it?
public class Stack<T> implements StackInterface<T> { . . . public T pop() { Node<T> oldTop = top; top = top.next; size--; return oldTop.item; } }
What about peeking at the top?
int top = stack.peek();
And how would you implement it?
What about peeking at the top?
int top = stack.peek();
And how would you implement it?
public class Stack<T> implements StackInterface<T> { . . . public T peek() { return top.item; } }
But what about throwing exceptions, using our brand-new StackException class?
public class Stack<T> implements StackInterface<T> { . . . public T pop() throws StackException { if (!isEmpty()) { Node<T> oldTop = top; top = top.next; size--; return oldTop.item; } else { throw new StackException("StackException: pop() attempt on empty stack"); } } public T peek() throws StackException { if (!isEmpty()) { return top.item; } else { throw new StackException("StackException: peek() attempt on empty stack"); } } public boolean isEmpty() { return top == null; // or size == 0 } }
Purposes:
public interface ListInterface<T> { . . . } public class ListArray<T> implements ListInterface<T> { . . . } public class ListReferences<T> implements ListInterface<T> { . . . } public class Stack<T> { protected ListInterface<T> list; // list can be instance of any // class that implements ListInterface<T> public Stack(String kindOf) { // Stack<Integer> s = new Stack<Integer>("array"); // Stack<Integer> s = new Stack<Integer>("references"); if (kindOf.equals("array")) { list = new ListArray<T>(); } else if (kindOf.equals("references")) { list = new ListReferences<T>(); } else { throw java.lang.RuntimeException("Stack constructor: argument " + kindOf + " not recognized."); } } . . . }
Related to first assignment…
A parameterized type in one class can be “passed” to another class.
public class A<T> { protected B<T> aBobject; public A() { aBobject = new B<T>(); } } public class B<T> { protected T item; public B(T itemArg) { item = itemArg; } }
Recognize whether a string is in the language
Algorithm:
Evaluating a postfix expression is easy with a stack.
The expression is in postfix notation.
Algorithm:
Differences from stack:
enqueue rather than pushdequeue rather than poppublic interface QueueInterface<T> { public boolean isEmpty(); public void enqueue(T newItem) throws QueueException; public T dequeue() throws QueueException; public T peek() throws QueueException; }
public class QueueException extends java.lang.RuntimeException { public QueueException(String s) { super(s); } }
First, let's create a queue. Let's say it will hold integers.
Queue<Integer> queue = new Queue<Integer>();
public class Queue<T> implements QueueInterface<T> { Node<T> lastNode; int size; public Queue() { lastNode = null; size = 0; } }
Now, try pushing something on the queue.
queue.enqueue(42);
How would you implement this?
public class Queue<T> implements QueueInterface<T> { . . . public void enqueue(T newItem) { Node<T> newNode = new Node<T>(newItem, null); if (isEmpty()) { newNode.next = newNode; // points to itself } else { newNode.next = lastNode.next; lastNode.next = newNode; } lastNode = newNode; size++; } }
Now, what if we enqueue again?
queue.enqueue(62);
What will the linked list look like?
And now, dequeue from the front.
int top = queue.dequeue();
What will the list look like?
And now, dequeue the top.
int top = queue.dequeue();
What will the list look like?
And how would you implement it?
And how would you implement it?
public class Queue<T> implements QueueInterface<T> { . . . public T dequeue() { Node<T> firstNode = lastNode.next; if (firstNode == lastNode) { // just one item in queue lastNode = null; } else { lastNode.next = firstNode.next; } size--; return firstNode.item; } }
What about peeking at the front?
int top = queue.peek();
And how would you implement it?
What about peeking at the front?
int top = queue.peek();
And how would you implement it?
public class Queue<T> implements QueueInterface<T> { . . . public T peek() { return lastNode.next.item; } }
But what about throwing exceptions, using our brand-new QueueException class?
In dequeue and peek check for empty queue just as we did for pop and peek for the stack.
Buffer of items. Enqueue them as acquired, dequeue them to use.
Palindromes, like “abccba”.
Event-based simulation.
Array-based implementation of queue. Circular array.
Deque (“deck”), a double ended queue.