Upload
beverley-houston
View
226
Download
3
Embed Size (px)
Citation preview
Operations on a Stack
• Create an empty stack• Is the stack empty?• Add a new item to the stack. (Push)• Remove the item that was most recently
added (Pop)• Retrieve the item that was most recently
added (Peek)
Implementing a Stack
• All items in the stack must be stored• Only the top item needs to be accessible for retrieval• Therefore a stack is a restricted form of list
– Use the List interface– Use an array (as inside ArrayList)– Use linked nodes (as inside LinkedList)
• Java does none of these - it uses a vector (growable array)– But, to understand stacks better, we will consider the 3
options above
Implementing using a List
//Complete code pp. 272-273
public class ListStack < E > {
private List < E > theData;
public Stack < E > {
theData = new ArrayList < E>();
}
//more methods here
}
ArrayList Implementation
• Push adds to the list– Where? Why?
• Pop removes an item– Which one?
• Peek looks at the top item– Where is it?
• ArrayList takes care of resizing the list, details of implementations
Empty and Push Method
Public boolean empty() {
return theData.size() == 0;
}
public E push (E obj){
//add at end of ArrayList
theData.add (obj);
return (obj);
}
Peek
public E peek() {
if (empty())
throw new EmptyStackException();
//top is at the end of the array
return theData.get(theData.size()-1);
}
Pop
public E pop() {
if (empty())
throw new EmptyStackException();
//top is at the end of the array
//recall: remove returns the object removed
return theData.remove(theData.size()-1);
}
And now more detail…
• Pretend we don’t already have ArrayList or LinkedList, and had to implement all from scratch
• Why?– Understand in detail how stacks work– See the differences and tradeoffs between array
and linked stacks– Appreciate how much easier it is to implement a
stack than a list (either type)
Array Implementation
• Push: insert element into the array (where?)• Peek: retrieve the most recently inserted
element (where is it?)• Pop: remove the most recently inserted
element (how)?
• Static vs. dynamic array?
Array Push, Pop
• All stack elements go into the array (in order)• Newest element is last (highest index) in the
array• Integer variable “top” indicates index of top• Push increments top• Pop decrements top
– Popped elements stay in array until overwritten by new push
Choices for top
• Top points after the top element– Push: first copy, then increment– Top: A[top-1]– Pop(item): first decrement, then copy
• If top points at the top element– Push: first increment, then copy– Top: A[top]– Pop(item): copy item, decrement
Example: Top at
• Empty stack (top = –1)
• Push ‘a’, Push ‘b’, Push ‘c’ (top=2)
• Pop, Pop (top = 0)
• Push ‘z’ (top = 1)
A[0]= A[1]= A[2]= A[3]= A[4]=
A[0]=‘a’ A[1]=‘b’ A[2]=‘c’ A[3]= A[4]=
A[0]=‘a’ A[1]=‘b’ A[2]=‘c’ A[3]= A[4]=
A[0]=‘a’ A[1]=‘z’ A[2]=‘c’ A[3]= A[4]=
Possible Errors
• Pop from empty stack• Top of empty stack
– Throw EmptyStackException
• Push if stack is full (CAPACITY items)– not a problem if resize is allowed (as in ArrayList)– If not, a FullStackException could be thrown
Class definition (data members)
public class ArrayStack < E >{
// array for the stack
E[ ] theData;
//index of top item
int topOfStack = -1;
Constructor and Check for Empty
//Initial capacityprivate static final int INITIAL_CAPACITY = 10;
//Construct an empty stackpublic ArrayStack() {
theData = (E[]) new Object[INITIAL_CAPACITY]; }
//Empty? public boolean empty(){ return top == -1; }
Push
• //Push an item onto the stackpublic E push(E obj){
if (topOfStack == theData.length-1) {
reallocate(); //or could throw an exception
}
//++top increments first, returns new value
theData[++topOfStack] = obj;
return obj
}
Pop
• //Pop an item from a stack and return itpublic E Pop(){
if (empty())
throw new EmptyStackException();
else
return theData[topOfStack--];
}
Efficiency of stack
• Push: constant time– Even though insert into array is not! (why?)
• Pop: constant time– Even though delete from array is not!
Node (Linked-List) Implementation
• Push: insert element into the list (where?)• Peek: retrieve the most recently inserted
element (where is it?)• Pop: remove the most recently inserted
element (how)?• isEmpty: (how do you know the stack is
empty?)• What special cases require exceptions?
Linked implementation
• Underlying data structure is a singly linked list• Push inserts at the beginning of the list
– Exception: cannot allocate a new node
• Pop removes from the beginning of the list– Exception: empty list (stack)
• Empty stack when top is null
Example (Linked Implementation)
• Empty stack
• Push ‘a’, Push ‘b’, Push ‘c’
• Pop, Pop
• Push ‘z’
c b a
a
z a
Class Definition
Public class LinkedStack {
private Node<E> topOfStackRef = null;
…
private static class Node<E>{
//same as for linked list
}
};
empty & peek
• //Is the stack empty?Public boolean empty() {
return (topOfStackRef == null);
}
• //Get item from topPublic E peek() {
if (empty()) throw new EmptyStackException();
return topOfStackRef.data;
}
Push
• // push (add to beginning of list)public E push (E obj){
topOfStackRef =
new Node<E>(obj, topOfStackRef);
return obj;
}
Pop
• //Pop and recover old top itemPublic E pop(){
if (empty()) throw new EmptyStackException();
else{
E result = topOfStackRef.data;
topOfStackRef = topOfStackRef.next;
return result;
}
}
Nodes vs. Arrays
• Array is simpler, requires extra space (unused capacity)
• Node uses minimum amount of space• Push and pop are O(1) either way• We never need to access the middle of the list.
• Note: replace ArrayList by LinkedList on slide 6 to get the list functionality without writing any new code. You must also replace add() by addFirst() in push, and remove() by removeFirst() in pop.
Postfix Expressions
• Also called RPN (reverse Polish notation)– Enter first operand, then second operand, then
operator– (Operands can be recursive expressions)– Example
• 1+(2*3) becomes 1 2 3 * +• First operand is 1• Second operand is (recursively) 2 3 *• Operator is +
Stacks Evaluate Postfix
• Reading the data:If you see an operand (number), push it
If you see an operator,
pop the first two items off the stack
perform the operation
push the result back on the stack
• Example: 1 2 3 * +– Push 1, push 2, push 3, pop 3, pop 2, push 6– Pop 6, pop 1, push 7
Infix Expressions
• Infix expressions are the kind we use in Java– 6*3+7 – 6+3*7– (6+3) * 7
• Order of operation depends on precedence– Multiplication first, then addition– Parentheses override order– Otherwise, left to right
Converting Infix to Postfix
• Operands (numbers) stay in the same order• Operators go in after their operands are
complete– 6*3+7 - 6 3 * 7 +– 6+3*7 6 3 7 * +– (6+3) * 7 6 3 + 7 *
• How to decide when to insert the operator?
Algorithm for Infix to Postfix
• For each token– If it is an operand, insert it immediately in the
result– If it is an operator– While stack is not empty AND this operator has
lower precedence than top-of-stack operator– pop operator from stack into expression– push this operator
• Pop remaining operators into expression
What about parentheses?
• When you see a left parenthesis, push it on the stack
• When you see a right parenthesis, pop all operators back to the left paren
• Why?– Parentheses delimit a new expression– Right paren acts like end of expression (pop all
remaining operators at the end)
A Search Problem
• Given a sequence of flight segments, can you reach one city from the other?
• If there is a flight from A to B, then A and B are adjacent (A->B)
• If (A->B) and (B->C), we can reach C from A
Recursive Solution (pseudocode)
bool canReach(city A, city B){If (A == B) return true; //trivial problem
If (adjacent(A,B)) return true; //direct flight
For (each city adjacent to A)
if canReach(city, B) return true;
Return false;
}
Stack-based solution (pseudocode)
bool canReach(city A, city B){If (A == B) return true; //trivial problemElse push A onto the stackWhile(stack is not empty and top != B) if the city has an unvisited neighbor
mark the neighbor as visited push the neighbor on the stack
else pop the stack; }If the stack is empty return false;Otherwise return true (and the path is on the stack!)}