STACK
Stack ADT 2 A stack is an abstract data type based on the list data model All operations are performed at one end of the list called the top of the stack (TOS) LIFO (for last-in first-out) list is a synonym for stack Common operations:! push(x) puts the element x on top of the stack! pop removes the topmost element from the stack.
Java Stack Interface 3 public interface Stack { public void push(object x); public Object pop(); public Object peek(); public boolean isempty(); public void clear(); }
From interface to implementation 4 Given that we want to support some interface, the designer still faces a choice! What will be the best way to implement this interface for my expected type of use?! Choice of implementation can reflect many considerations Major factors we think about! Speed for typical use case! Storage space required
Array implementation of Stack 5 class ArrayStack implements Stack { max-1 } private Object[] array; //Array that holds the Stack private int index = 0; //First empty slot in Stack public ArrayStack(int maxsize) { array = new Object[maxSize]; } public void push(object x) { array[index++] = x; } public Object pop() { return array[--index]; } public Object peek() { return array[index-1]; } public boolean isempty() { return index == 0; } public void clear() { index = 0; } Question: What can go wrong? index 4 3 2 1 0 O(1) worstcase time for each operation. What if maxsize is too small?
Linked List Implementation of Stack 6 class ListStack implements Stack { private Node head = null; //Head of list that //holds the Stack public void push(object x) { head = new Node(x, head); } public Object pop() { Node temp = head; head = head.next; return temp.data; } public Object peek() { return head.data; } public boolean isempty() { return head == null; } public void clear() { head = null; } } O(1) worst-case time for each operation (but constant is larger) Note that array implementation can overflow, but the linked list version cannot head
Use of Stack 7 Infix to postfix conversion Postfix evaluation Function calls etc
Infix to postfix 8 When an operand is read, output it When ( is read, push it When an operator is read:! If TOS item has higher or equal precedence, repeatedly pop until TOS has an element of lower precedence or stack empty, then push the operator! If the stack is empty or TOS item has lower precedence, just push it When ) is found, pop until we find the matching ( ( has the lowest precedence when in the stack but has the highest precedence when in the input When we reach the end of input, pop until the stack is empty
9 Stack: Output:
10 Stack: ( Output:
11 Stack: ( Output: 8
12 Stack: ( + Output: 8
13 Stack: ( + Output: 8 9
14 Stack: ( + * Output: 8 9
15 Stack: ( + * ( Output: 8 9
16 Stack: ( + * ( Output: 8 9 4
17 Stack: ( + * ( + Output: 8 9 4
18 Stack: ( + * ( + Output: 8 9 4 5
19 Stack: ( + * ( + * Output: 8 9 4 5
20 Stack: ( + * ( + * Output: 8 9 4 5 7
21 Stack: ( + * ( + Output: 8 9 4 5 7 *
22 Stack: ( + * ( Output: 8 9 4 5 7 * +
23 Stack: ( + * ( + Output: 8 9 4 5 7 * +
24 Stack: ( + * ( + Output: 8 9 4 5 7 * + 6
25 Stack: ( + * ( Output: 8 9 4 5 7 * + 6 +
26 Stack: ( + * Output: 8 9 4 5 7 * + 6 +
27 Stack: ( + Output: 8 9 4 5 7 * + 6 + *
28 Stack: ( Output: 8 9 4 5 7 * + 6 + * +
29 Stack: Output: 8 9 4 5 7 * + 6 + * +
30 Stack: + Output: 8 9 4 5 7 * + 6 + * +
31 Stack: + Output: 8 9 4 5 7 * + 6 + * + 3
32 Stack: + * Output: 8 9 4 5 7 * + 6 + * + 3
33 Stack: + * Output: 8 9 4 5 7 * + 6 + * + 3 5
34 Stack: + Output: 8 9 4 5 7 * + 6 + * + 3 5 *
35 Stack: Output: 8 9 4 5 7 * + 6 + * + 3 5 * +
36 Stack: + Output: 8 9 4 5 7 * + 6 + * + 3 5 * +
37 Stack: + Output: 8 9 4 5 7 * + 6 + * + 3 5 * + 4
38 Stack: Output: 8 9 4 5 7 * + 6 + * + 3 5 * + 4 +
More Examples 39 Refer to the slides by Otávio Braga linked from the class website
Postfix evaluation 40 Starting with an empty stack, we scan the postfix expression from left to right Each time we encounter an argument, we push it onto the stack When we encounter an operator, we pop the stack twice, remembering the operands popped We then apply the operator to the two popped values (with the second as the left operand) and push the result onto the stack
41 Evaluating 3 4 + 2 *
Postfix to Expression Tree 42 A 2 * 2 A * B * - B 2 * + A B - / 1. Push A 2. Push 2 3. Pop 2 4. Pop A 5. Create tree_1 6. Push tree_1 7. Push 2 8. Push A 9. Pop A 10. Pop 2 11. Create tree_2 12. Push tree_2 13. Push B 14. Pop B 15. Pop tree_2 16. Create tree_3 17. Push tree_3 18. Pop tree_3 19. Pop tree_1 20. Create tree_4 21. Push tree_4 22. Push B 23. Push 2 24. Pop 2 25. Pop B 26. Create tree_5 27. Push tree_5 28. Pop tree_5 29. Pop tree_4 30. Create tree_6 31. Push tree_6 32. Push A 33. Push B 34. Pop B 35. Pop A 36. Create tree_7 37. Push tree_7 38. Pop tree_7 39. Pop tree_6 40. Create tree_8 41. Push tree_8 tree_1 tree_4 tree_2 tree_6 tree_3 tree_8 tree_5 tree_7
Evaluating expression tree 43 If at leaf node (operand node) return the operand s value Otherwise: Evaluate the left sub-tree Evaluate the right sub-tree Combine the results from both sub-trees with the operator at root public static int eval(treecell root) { int left_result, right_result; if (root.datum is operand) return operand s value; left_result = eval(root.left); right_result = eval(root.right); switch (root.datum) { case + : return left_result + right_result; case * : return left_result * right_result; : : } }
Function calls 44 An important application of stacks is normally hidden from view! A stack is used to allocate space in the computer s memory to the variables belonging to the various functions of a program Example: a recursive factorial function! Has a parameter n and a return value! As fact calls itself recursively, different calls with different parameter are active at the same time! A frame for each call is created and place on TOS! When a given call return, its frame gets popped off
public static int factorial(int 3) { int fact; if (n > 1) fact = factorial(2) * 3; else fact = 1; return fact; }
public static int factorial(int 3) { int fact; if (n > 1) fact = factorial(2) * 3; else fact = 1; return fact; } public static int factorial(int 2) { int fact; if (n > 1) fact = factorial(1) * 2; else fact = 1; return fact; }
public static int factorial(int 3) { int fact; if (n > 1) fact = factorial(2) * 3; else fact = 1; return fact; } public static int factorial(int 2) { int fact; if (n > 1) fact = factorial(1) * 2; else fact = 1; return fact; } public static int factorial(int 1) { int fact; if (n > 1) fact = factorial(n - 1) * n; else fact = 1; return fact; }
public static int factorial(int 3) { int fact; if (n > 1) fact = factorial(2) * 3; else fact = 1; return fact; } public static int factorial(int 2) { int fact; if (n > 1) fact = factorial(1) * 2; else fact = 1; return fact; } public static int factorial(int 1) { int fact; if (n > 1) fact = factorial(n - 1) * n; else fact = 1; return 1; }
public static int factorial(int 3) { int fact; if (n > 1) fact = factorial(2) * 3; else fact = 1; return fact; } public static int factorial(int 2) { int fact; if (n > 1) fact = 1 * 2; else fact = 1; return fact; } public static int factorial(int 1) { int fact; if (n > 1) fact = factorial(n - 1) * n; else fact = 1; return 1; }
public static int factorial(int 3) { int fact; if (n > 1) fact = factorial(2) * 3; else fact = 1; return fact; } public static int factorial(int 2) { int fact; if (n > 1) fact = 1 * 2; else fact = 1; return 2; }
public static int factorial(int 3) { int fact; if (n > 1) fact = 2 * 3; else fact = 1; return fact; } public static int factorial(int 2) { int fact; if (n > 1) fact = 1 * 2; else fact = 1; return 2; }
public static int factorial(int 3) { int fact; if (n > 1) fact = 2 * 3; else fact = 1; return 6; }