Chapter 7: Stacks

Chapter 7: Stacks · Study Questions
The stack ADT and LIFOArray and linked implementationsAmortized analysisStack applicationsHanoi and stock spanInfix, postfix, prefix
Sercan KÜLCÜ · Giresun University · Computer Engineering

Short Answer · The Stack ADT

Question 1: push/pop Output

What does this code print?

Deque<Integer> s = new ArrayDeque<>();
s.push(4); s.push(9); s.push(2);
System.out.print(s.pop() + " ");
s.push(7);
System.out.print(s.peek() + " ");
System.out.print(s.pop() + s.pop() + " ");
s.push(5);
System.out.print(s.size() + " " + s.peek());
Show answer

Output: 2 7 16 2 5

  • 4, 9, 2 are pushed; 2 is on top, so pop() returns 2 (LIFO). Stack (bottom→top): 4 9.
  • 7 is pushed; peek() returns 7 without removing it.
  • s.pop() + s.pop() is integer addition first: 7 + 9 = 16. Stack: 4.
  • 5 is pushed: the stack is 4 5 → size() is 2, peek() is 5.

Short Answer · The Stack ADT

Question 2: An Operation Sequence and the Final Stack

These operations run in order on an empty stack. What does each pop() return? What is left on the stack at the end, and which item is on top?

push(5), push(3), pop(), push(8),
push(1), pop(), pop(), push(4)
Show answer
  • push(5), push(3) → [5, 3]; pop() → 3
  • push(8), push(1) → [5, 8, 1]; pop() → 1; pop() → 8
  • push(4) → [5, 4]

The pops return 3, 1, 8. The stack ends as 5, 4 from bottom to top, with 4 on top.

Multiple Choice · The Stack ADT

Question 3: Possible Output Orders

The numbers 1, 2, 3, 4 are pushed in that order, and pop() may be called at any point in between. Which order of popped values is impossible?

C: if 4 comes out first, then 1, 2, 3 are still on the stack with 3 on top, so the next pop must return 3, not 2. A is possible: push 1, 2, 3 → pop 3, pop 2 → push 4, pop 4 → pop 1.

Multiple Choice · The Stack ADT

Question 4: top and size in an Array Stack

In an array-based stack of capacity cap, top is the index of the top item, and an empty stack has top = −1. What are the “full” condition and size()?

B: the last valid index is cap − 1, and since indices start at 0, the number of items is top + 1. A is the classic top/size mix-up: once top == cap, data[top] is already outside the array.

Short Answer · Implementation

Question 5: The Popped Cell

This pop() for an array-based stack of objects returns the right value but has a flaw. What is the flaw, and how do you fix it?

public E pop() {
  if (isEmpty())
    throw new RuntimeException("empty");
  return data[top--];
}
Show answer

The popped item's reference stays in cell data[top+1]. The stack no longer uses the object, but because the array still points to it, the garbage collector cannot reclaim it (a memory leak known as loitering).

public E pop() {
  if (isEmpty())
    throw new RuntimeException("empty");
  E x = data[top];
  data[top--] = null; // let go
  return x;
}

The operation is still O(1). A stack of a primitive type (int[]) doesn't have this problem.

Code Trace · Implementation

Question 6: Tracing a Bounded Array Stack

This code uses the ArrayStack class from the lecture. What are the data array and top after each line, and what does the program print?

Three cells, all null; an empty stack has top = −1.

top (−1) ≠ 2 → there is room. data[++top] = 10: top becomes 0 first, then the write happens.

top becomes 1; data[1] = 20.

x = data[1] = 20 is saved, the cell is set to null, and top drops to 0; 20 is printed (LIFO).

The freed cell 1 is reused: data[1] = 30.

top becomes 2; data[2] = 40. The array is now full.

top() returns 40 without removing it; size() = top + 1 = 3.

top == data.length − 1 (2 == 2) → overflow exception. A dynamic array would grow here.

ArrayStack<Integer> s = new ArrayStack<>(3);
s.push(10);
s.push(20);
System.out.println(s.pop());
s.push(30);
s.push(40);
System.out.println(s.top() + " " + s.size());
s.push(50);

Short Answer · Implementation

Question 7: The Cost of Doubling

An empty stack starts with capacity 1 and doubles its capacity whenever it is full (copying the old items into the new array). We push 9 times. How many copies and how many writes happen in total, what is the final capacity, and what does this say about the amortized cost of push?

Show answer
push no.123456–89
growth—1→22→4—4→8—8→16
copies0120408

Copies: 1 + 2 + 4 + 8 = 15; writes: 9; total 24; final capacity 16.

24 < 3n = 27: over n pushes the copies total 1 + 2 + 4 + … < 2n, so the total is < 3n and the average per push is < 3 → amortized O(1). A single push that grows the array (the 9th) still takes O(n); the amortized bound is an average over a long sequence of operations.

Multiple Choice · Implementation

Question 8: Growing by a Fixed Amount

Instead of doubling, a dynamic-array stack adds 10 cells whenever it is full (10 → 20 → 30 → …). For n pushes onto an empty stack, what are the total cost and the average cost per push?

C: the copies total 10 + 20 + 30 + … + n ≈ n²/20 → O(n²); divided over n pushes, that is O(n) each. A holds only when capacity grows proportionally (e.g., ×2): then the copies form a geometric series and the total stays < 3n.

Multiple Choice · Implementation

Question 9: Array or Linked List?

Which statement about stack implementations is false?

A is false: a push that grows the array copies every item and takes O(n); only the amortized cost is O(1). D is true: Stack is Vector-based and synchronized, which makes it slower. In a linked list, the next reference in each item costs extra memory.

Short Answer · Applications

Question 10: Tracing Bracket Matching

What does the lecture's isBalanced method return for the input "[{()()}]{"? Show the stack after each character.

Show answer
CharacterActionStack (bottom→top)
[ { (3 × push[ { (
)pop ( ✓[ {
(push[ { (
)pop ( ✓[ {
}pop { ✓[
]pop [ ✓empty
{push{
(end)stack empty?{ left

Result: false. Every closer matched, but an unclosed { is left at the end, so return stack.isEmpty() gives false. Time O(n); the stack holds at most O(n).

Multiple Choice · Applications

Question 11: The Empty-Stack Check

If the marked line is removed from isBalanced, which input throws an exception?

for (char c : s.toCharArray()) {
  if (c == '(' || c == '[' || c == '{') {
    stack.push(c);
  } else {
    if (stack.isEmpty()) return false; // removed
    char open = stack.pop();
    if (!matches(open, c)) return false;
  }
}
return stack.isEmpty();

D: after "()" matches and the stack empties, the second ) pops an empty ArrayDeque → NoSuchElementException. A doesn't throw: ( is left at the end and the method returns false. In B, [ is on top when ) arrives, so they don't match → false; C is balanced → true.

Short Answer · Applications

Question 12: Next Greater Element

What does nextGreater(new int[]{6, 2, 9, 5, 5, 7, 1}) return? Show how the stack changes as the array is scanned from right to left.

for (int i = arr.length-1; i >= 0; i--) {
  while (!stack.isEmpty() &&
         stack.peek() <= arr[i])
    stack.pop();
  result[i] = stack.isEmpty()
           ? -1 : stack.peek();
  stack.push(arr[i]);
}
Show answer
iarr[i]poppedresult[i]stack (bottom→top)
61—−11
571−17
45—77 5
355 (≤ 5)77 5
295, 7−19
12—99 2
06299 6

Result: [9, 9, −1, 7, 7, −1, −1]. The stack stays decreasing from bottom to top (a monotonic stack). Each item is pushed at most once and popped at most once → O(n) (brute force is O(n²)).

Short Answer · Applications

Question 13: A Stack with O(1) getMin

We run push(4), push(6), push(2), push(2), pop(), getMin(), pop(), getMin() in order. What do the two getMin() calls return, and what is left on the min stack at the end?

void push(int x) {
  s.push(x);
  if (min.isEmpty() || x <= min.peek())
    min.push(x);
}
int pop() {
  int x = s.pop();
  if (x == min.peek()) min.pop();
  return x;
}
int getMin() { return min.peek(); }
Show answer
  • After the pushes, s (bottom→top) is 4 6 2 2 and min is 4 2 2 (6 is skipped because 6 > 4; the second 2 goes in thanks to <=).
  • pop() → 2; 2 == min.peek() → min: 4 2. getMin() → 2.
  • pop() → 2; min: 4. getMin() → 4.

At the end the min stack holds 4. getMin only peeks → O(1).

With < instead, the second 2 would not go onto min, the first pop would remove min's only 2, and the first getMin() would wrongly return 4 (a 2 is still on the stack).

Code Trace · Hanoi and Stock Span

Question 14: Tracing Stock Span

What array does span({30, 20, 25, 10, 15, 40}) return?

First day: push index 0; span 1. The stack holds the indices of days not yet beaten.

20 ≥ prices[0] = 30? No → span = 1 − 0 = 1; push(1).

25 ≥ prices[1] = 20 → pop(1). Day 1 can no longer be anyone's boundary.

25 < 30 → stop. span = 2 − 0 = 2; push(2).

10 < 25 → span = 3 − 2 = 1; push(3).

15 ≥ prices[3] = 10 → pop(3).

15 < 25 → span = 4 − 2 = 2; push(4).

40 ≥ 15 → pop(4); 40 ≥ 25 → pop(2).

40 ≥ 30 → pop(0). The stack is empty: 40 beats every earlier price.

The stack is empty → span = i + 1 = 6; push(5).

Each index is pushed once and popped at most once → O(n).

int[] span(int[] prices) {
  int[] spans = new int[prices.length];
  Deque<Integer> stack = new ArrayDeque<>();
  stack.push(0); spans[0] = 1;
  for (int i = 1; i < prices.length; i++) {
    while (!stack.isEmpty() &&
        prices[i] >= prices[stack.peek()])
      stack.pop();
    spans[i] = stack.isEmpty() ? i + 1
               : i - stack.peek();
    stack.push(i);
  }
  return spans;
}

Multiple Choice · Expression Notation

Question 15: Right-Associative Power

^ (power) has the highest precedence and associates right to left. What is the postfix form of A ^ B ^ C * D?

C: right associativity means (A ^ (B ^ C)) * D. Option A reflects (A ^ B) ^ C, that is, left associativity. This is why, when ^ arrives, the algorithm does not pop an equal-precedence ^ from the top; it pops only operators of higher precedence.

Code Trace · Expression Notation

Question 16: Tracing Infix → Postfix

What string does infixToPostfix("A-B*(C+D)/E") return?

Precedence: + − → 1, * / → 2, ( → 0.

Operand → straight to the output.

The stack is empty → push(−).

Operand → output.

Top − (1) ≥ * (2)? No → push(*).

( is always pushed.

Operand → output.

( is on top (precedence 0) → nothing is popped; push(+).

Operand → output.

) → pop until (: + goes to the output.

( is discarded; parentheses never reach the output.

Top * (2) ≥ / (2) → * goes to the output (left associativity).

Top − (1) ≥ 2? No → push(/).

Operand → output.

End of input: / and then − go to the output. Result: A B C D + * E / −. O(n).

for (char c : expr.toCharArray()) {
  if (Character.isLetterOrDigit(c))
    out.append(c);
  else if (c == '(') stack.push(c);
  else if (c == ')') {
    while (stack.peek() != '(')
      out.append(stack.pop());
    stack.pop();  // discard '('
  } else {        // operator
    while (!stack.isEmpty() &&
        prec(stack.peek()) >= prec(c))
      out.append(stack.pop());
    stack.push(c);
  }
}
while (!stack.isEmpty())
  out.append(stack.pop());

Short Answer · Expression Notation

Question 17: Postfix Evaluation

Find the result of evaluatePostfix("623+*84/-"), writing down the operand stack after each token.

Show answer
ReadActionStack (bottom→top)
6, 2, 33 × push6 2 3
+right = 3, left = 2 → 2 + 3 = 56 5
*right = 5, left = 6 → 6 · 5 = 3030
8, 42 × push30 8 4
/right = 4, left = 8 → 8 / 4 = 230 2
−right = 2, left = 30 → 30 − 2 = 2828

Result: 28 (in infix, 6 * (2 + 3) − 8 / 4). One value is left on the stack at the end. No parentheses or precedence are needed, and each token is handled once → O(n).

Multiple Choice · Expression Notation

Question 18: Operand Order

What does the lecture's evaluatePostfix("82/3-") return?

if (Character.isDigit(c)) {
  stack.push(c - '0');
} else {
  int right = stack.pop();
  int left = stack.pop();
  stack.push(apply(left, c, right));
}

D: for /, right = 2 is popped first and then left = 8 → 8 / 2 = 4; for −, right = 3, left = 4 → 4 − 3 = 1. A (3) comes from mixing up the operand order: 2 / 8 = 0 (integer division), then 3 − 0 = 3. The first pop is the right operand, the second the left.

Multiple Choice · Summary

Question 19: Print Order

What does this code print?

Stack<Integer> s = new Stack<>();
Deque<Integer> d = new ArrayDeque<>();
for (int i = 1; i <= 3; i++) {
  s.push(i);
  d.push(i);
}
System.out.println(s + " " + d);

A: the legacy Stack (Vector-based) prints and iterates bottom to top, while ArrayDeque goes top to bottom (push adds at the front). The two stacks hold the same items, yet the output looks reversed; a for-each loop shows the same difference.

Multiple Choice · Expression Notation

Question 20: Infix → Prefix

What does the lecture's infixToPrefix (reverse, swap ( ↔ ), run postfix without popping on equal precedence, reverse the result) return for "A-B+C*D/E"?

B: left associativity means (A − B) + ((C * D) / E). A results from popping on equal precedence in step 3 as well; after the reversal the grouping runs right to left: A − (B + C * (D / E)). C is the postfix form of the expression. D is the output of step 3, with the final reversal forgotten.

Short Answer · Hanoi and Stock Span

Question 21: The Hanoi Task Stack

The lecture's stack-based hanoi method is called as hanoi(4); Task(n, from, via, to) means “move n disks from from to to using via”. After the first three pops, which tasks are on the stack (top to bottom)? What is the first move printed, and what is the most tasks the stack ever holds?

stack.push(new Task(n, 'A', 'B', 'C'));
while (!stack.isEmpty()) {
  Task t = stack.pop();
  if (t.n() == 1)
    System.out.println(t.from() + " → " + t.to());
  else {             // reverse order
    int m = t.n() - 1;
    stack.push(new Task(m, t.via(), t.from(), t.to()));
    stack.push(new Task(1, t.from(), t.via(), t.to()));
    stack.push(new Task(m, t.from(), t.to(), t.via()));
  }
}
Show answer
poppoppedstack (top to bottom)
1(4,A,B,C)(3,A,C,B) (1,A,B,C) (3,B,A,C)
2(3,A,C,B)(2,A,B,C) (1,A,C,B) (2,C,A,B) (1,A,B,C) (3,B,A,C)
3(2,A,B,C)(1,A,C,B) (1,A,B,C) (1,B,A,C) (1,A,C,B) (2,C,A,B) (1,A,B,C) (3,B,A,C)

The 4th pop, (1,A,C,B), gives the first move: A → B (disk 1). Because n is even, the smallest disk goes to B first; in hanoi(3) the first move was A → C.

Each expansion removes 1 task and adds 3 (net +2), and this happens n − 1 times in a row, so the stack holds at most 7 = 2n − 1 tasks. In all, 2⁴ − 1 = 15 moves are printed.

Multiple Choice · Applications

Question 22: Call Stack Depth

When the call stack is at its deepest, how many frames does it hold (counting main), and which frame is on top?

int fact(int n) {
  if (n <= 1)
    return 1;
  return n * fact(n - 1);
}
// in main:
System.out.println(fact(4));

D: main → fact(4) → fact(3) → fact(2) → fact(1). The base case is n <= 1, so fact(0) is never called (B). C forgets main's frame. A reads the stack upside down: fact(4) sits just above main, and the most recent call is on top. Depth n + 1 → O(n) memory.

Multiple Choice · Applications

Question 23: StackOverflowError

The base case is written as n == 1. What happens when fact(0) is called?

int fact(int n) {
  if (n == 1)
    return 1;
  return n * fact(n - 1);
}
// in main:
System.out.println(fact(0));

A: n = 0, −1, −2, … never reaches the base case; each call pushes a new frame, and when the thread's limited stack space fills up, the JVM throws StackOverflowError. D would be right for an infinite loop; in recursion every call uses memory, so the program crashes. B and C assume the base case catches 0; with n <= 1 it would return 1.

Short Answer · Applications

Question 24: Tracing Back / Forward

The browser follows the two-stack rules from the lecture: visit → push the current page onto back and clear forward; back → push the current page onto forward and pop back; forward → push the current page onto back and pop forward.

The current page is Home and both stacks are empty. We run visit(Mail), visit(Maps), visit(Video), back(), back(), forward(), visit(Blog), back() in order. Write both stacks and the current page after each operation. At the end, can forward() take us back to Video?

Show answer
Operationback (bottom→top)currentforward (bottom→top)
visit(Mail)HomeMailempty
visit(Maps)Home MailMapsempty
visit(Video)Home Mail MapsVideoempty
back()Home MailMapsVideo
back()HomeMailVideo Maps
forward()Home MailMapsVideo
visit(Blog)Home Mail MapsBlogempty
back()Home MailMapsBlog

At the end, forward() opens Blog. Video is out of reach: visit(Blog) started a new path and cleared the forward stack, which held Video. Each operation is O(1).

The End

Chapter 7: Stacks: Study Questions
Lecture slides: Chapter 7: Stacks
1 / 1 Sercan KÜLCÜ. All rights reserved.