670 likes | 799 Views
Chapter 3. Stacks. Chapter Objectives. Stack and its methods push pop peek empty Java Stack implementation Array/Linked List implementation Applications finding palindromes balanced parentheses arithmetic expressions. Stack Abstract Data Type. Section 3.1. Stack Abstract Data Type.
E N D
Chapter 3 Stacks
Chapter Objectives • Stack and its methods • push • pop • peek • empty • Java Stack implementation • Array/Linked List implementation • Applications • finding palindromes • balanced parentheses • arithmetic expressions
Stack Abstract Data Type Section 3.1
Stack Abstract Data Type • Widely used in computer science • Only the top item can be accessed • extract only one item at a time • Storage policy • Last-In, First-Out, or LIFO
Specification • Top element is visible • We need the ability to • empty • peek • pop • push
Stack Interface • StackInt Interface
A Stack Operations • btf=name.empty(); • last = names.peek(); • temp = names.pop(); • names.push(“Philip”);
Stack Applications Section 3.2
Palindromes-Application 1 • Palindrome • a string that reads identically in either direction • Examples • kayak • "I saw I was I" • “Able was I ere I saw Elba” • "Level madam level" • Problem: • Use a program to determine if a string is a palindrome
Finding Palindromes Code import java.util.*; public class PalindromeFinder { private String inputString; private Stack<Character> charStack = new Stack<Character>(); public PalindromeFinder(String str) { inputString = str; fillStack(); // fills the stack with the characters in inputString } ...
Implement fillStack() • Push each string character onto a stack k a k y a k a y a k k a y a a k y private void fillStack() { for(int i = 0; i < inputString.length(); i++) { charStack.push(inputString.charAt(i)); } } k a y a k a k k
Implement buildReverse() • Pop each character off the stack k a a k k a k y a y k k a y a k a y a private String buildReverse(){ StringBuilder result = new StringBuilder(); while(!charStack.empty()) { result.append(charStack.pop()); } return result.toString(); } y a k a k k
Implement isPalindrome() ... public boolean isPalindrome() { return inputString.equalsIgnoreCase(buildReverse()); } }
Finding Palindromes (cont.) • PalindromeFinder Class
Testing • Test with the following inputs: • a single character (always a palindrome) • multiple characters in a word • multiple words • different cases • even-length strings • odd-length strings • the empty string (considered a palindrome)
Balanced Parentheses-Application 2 • Analyzing arithmetic expressions ( a + b * ( c / ( d – e ) ) ) + ( d / e ) • The solution is to use stacks!
Demonstration (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 0
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 1
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 2
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ [ ( ( ( balanced : true index : 3
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ ( ( balanced : true index : 4
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ ( ( balanced : true index : 5
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ ( ( balanced : true index : 6
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ ( ( ( Matches! Balanced still true balanced : true index : 7
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 8
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 9
Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( Matches! Balanced still true balanced : true index : 10
Testing • Provide a variety of input expressions • Try several levels of nested parentheses • Try nested parentheses where corresponding parentheses are not of the same type • Try unbalanced parentheses • No parentheses at all!
ParenChecker.java code • Listing 3.3-ParenChecker Code
Implementing a Stack Section 3.3
First way-using Vector public class Stack<E> extends Vector<E> • a growable array of objects • Elements of a Vector • can be accessed using an index • the size can grow or shrink
Implement push and pop • To implement push public E push(obj E) { add(obj); return obj; } • To implement pop public E pop throws EmptyStackException { try { return remove (size() – 1); } catch (ArrayIndexOutOfBoundsException ex) { throw new EmptyStackException(); } }
The problem is… • all Vector operations can be applied to a Stack • All the elements can be indexed • Violate information hiding rule • since only the top element of a stack should be accessible
Second way-using ArrayList • ArrayList • Implement push method public E push(E obj) { theData.add(obj); return obj; } • Adapter class • Method delegation
Code with a List Component • List 3.4-ListStack
Third way-Using an Array • If we implement a stack as an array, we would need . . . public class ArrayStack<E> implements StackInt<E> { private E[] theData; int topOfStack = -1; private static final int INITIAL_CAPACITY = 10; @SupressWarnings("unchecked") public ArrayStack() { theData = (E[])new Object[INITIAL_CAPACITY]; } Allocate storage for an array with a default capacity Keep track of the top of the stack (subscript of the element at the top of the stack; for empty stack = -1) There is no size variable or method
Implementation using Array Character Character Character Character value = 'a' value = 'J' value = 'v' value = 'a' ArrayStack Object[] theData = topOfStack = -1 [0] = null [1] = null [2] = null [3] = null [4] = null [5] = null [6] = null [7] = null [8] = null [9] = null 3 0 2 1 public E push(E obj) { if (topOfStack == theData.length - 1){ reallocate(); } topOfStack++; theData[topOfStack] = obj; return obj; }
Implementation using Array @Override public E pop() { if (empty()) { throw new EmptyStackException(); } return theData[topOfStack--]; }
The efficiency of using Array • This implementation is O(1), in contrast to the “kayak” example, which is O(n)
Fourth Way-using Linked List • We can also implement a stack using a linked list of nodes It is easiest to insert and delete from the head of a list push inserts a node at the head and pop deletes the node at the head when the list is empty, pop returns null
Using Linked-List: code • Listing 3.5 LinkedStack
Comparison among the Stack Implementations • Extending a Vectoris a poor choice • Because all Vector methods are accessible • The easiest implementation • uses a List component- ArrayList is the simplest) for storing data • Arraylist-requires reallocation of space • linked list-requires allocating storage for links • insertions and deletions • constant time, O(1)
More Stack Applications Section 3.4
Postfix evaluation-stack application • Postfix and infix notation • infix is popular • Postfix is also useful • No parentheses needed
How to Evaluate Postfix Expressions • Write a class that evaluates a postfix expression • Use the space as a delimiter between tokens
The Idea to Evaluate Postfix Expressions 4 4 7 * 20 - 4 1. create an empty stack of integers 2. while there are more tokens 3. get the next token 4. if the first character of the token is a digit 5. push the token on the stack 6. else if the token is an operator 7. pop the right operand off the stack 8. pop the left operand off the stack 9. evaluate the operation 10. push the result onto the stack 11. pop the stack and return the result
Evaluate Postfix Expressions 4 4 7 7 * 20 - 4 7 4 1. create an empty stack of integers 2. while there are more tokens 3. get the next token 4. if the first character of the token is a digit 5. push the token on the stack 6. else if the token is an operator 7. pop the right operand off the stack 8. pop the left operand off the stack 9. evaluate the operation 10. push the result onto the stack 11. pop the stack and return the result