Chapter 10: Search Trees

Chapter 10: Search Trees · Study Questions
The BST property and traversalSearch, insertion, successorDeletion and analysisRange queries and validationAVL treesRed-black treesSplay treesB-trees and B+ trees
Sercan KÜLCÜ · Giresun University · Computer Engineering

Multiple Choice · Search Trees

Question 1: The BST Property

Trees are written as root(left, right) (— means empty). Which of these is not a binary search tree?

C: 12 is right of 5, so it must exceed 5, but it is also in 10's left subtree, so it must be less than 10 too. The BST property covers whole subtrees, not just children. In B, 7 is between 5 and 10, so B is valid.

Multiple Choice · Search Trees

Question 2: A Buggy minValue

Here is a version of minValue. What does minValue(root) return for a non-empty tree?

BinaryTreeNode<E> minValue(
        BinaryTreeNode<E> node) {
    while (node != null)
        node = node.leftChild;
    return node;
}

The loop runs until node is null, walking past the leftmost node and returning null. No field of null is accessed, so no exception (C is wrong). The fix: while (node.leftChild != null); the minimum is the leftmost node, the one with no left child; O(h).

Multiple Choice · BST Operations

Question 3: Comparing with ==

1000, 100, and 2000 were added to the tree with insert, in that order. What does this search print?

boolean search(BinaryTreeNode<Integer> root,
               Integer data) {
    if (root == null) return false;
    if (data == root.data) return true;
    if (data.compareTo(root.data) < 0)
        return search(root.leftChild, data);
    return search(root.rightChild, data);
}
System.out.println(search(root, 1000));

== compares Integer references, and two separately boxed 1000s are different objects. compareTo returns 0, so the code goes right (to 2000) and hits the null on 2000's left → false. The fix: k = data.compareTo(root.data); k == 0 means found.

Short Answer · BST Operations

Question 4: Insertion Order and Tree Shape

Insert 45, 20, 70, 10, 30, 60, 90, 25, 65, 27 in that order into an empty BST. Draw the final tree and give its height.

Show answer
10202527304560657090

Each key descends from the root (left if smaller, right if larger) and becomes a leaf where it hits null. E.g., 27: 45 → 20 → 30 → 25 → right of 25.

Height 4 (the path 45–20–30–25–27).

Check with an inorder traversal: 10 20 25 27 30 45 60 65 70 90

Short Answer · BST Operations

Question 5: Dropping the Return Value

The slides' insert (which returns the new subtree root) is used as below. What is printed? Explain.

BinaryTreeNode<Integer> root = null;
insert(root, 8);
insert(root, 3);
insert(root, 12);
inorder(root);
Show answer

Nothing is printed; the tree stays empty. Java passes arguments by value: insert(null, 8) returns the new node, but it is never assigned, so it is lost and root stays null.

The fix: root = insert(root, 8); (and likewise for delete).

On a non-empty tree the unassigned call often seems to work, since the inner call links the new leaf via root.leftChild = …. But whenever the root changes (empty tree, deleting the root, a rotation at the root of a balanced tree), the tree breaks.

Short Answer · BST Operations

Question 6: Successor, Predecessor, Ceiling, Floor

For the BST shown, find successor(45), predecessor(50), ceiling(38), and floor(38), naming the rule you used for each.

20303540455060657080
Show answer
  • successor(45) = 50: 45 has no right subtree → the nearest ancestor we reach from its left (45 is in 50's left subtree).
  • predecessor(50) = 45: the largest key in the left subtree: one step left (30), then right all the way → 40 → 45.
  • ceiling(38) = 40: the smallest key ≥ 38 (38 is not in the tree).
  • floor(38) = 35: the largest key ≤ 38.

Each follows a single path from the root: O(h). The TreeMap equivalents are higherKey, lowerKey, ceilingKey, and floorKey.

Code Trace · BST Operations

Question 7: Tracing successor()

In the tree shown, which node does successor(root, 62) return? (62 is not in the tree.)

20303540455060657080
20303540455060657080

No candidate yet; start at the root (50).

20303540455060657080

62 ≥ 50 → neither 50 nor anything to its left can be the successor; go right.

20303540455060657080

62 < 70 → 70 is a candidate; a smaller one can only be on the left → go left.

20303540455060657080

62 ≥ 60 → go right.

20303540455060657080

62 < 65 → candidate = 65 (better than 70); go left: root = null.

20303540455060657080

The loop ends → return 65. We visited 4 nodes: O(h).

TreeNode successor(TreeNode root, int x) {
    TreeNode candidate = null;
    while (root != null) {
        if (x < root.data) {
            candidate = root;   // candidate
            root = root.left;   // left
        } else
            root = root.right;  // right
    }
    return candidate;
}
System.out.println(successor(root, 62).data);

Short Answer · BST Operations

Question 8: Deletion: Three Cases

Delete 20, 30, and 50, in that order, from the BST shown (use the inorder successor for two-child nodes). Name each deletion's case and draw the final tree.

20303540455060657080
Show answer
  • delete 20: a leaf → 30's left link becomes null.
  • delete 30: it now has only a right child (40) → one child: 50 links directly to 40.
  • delete 50: two children → successor = smallest key on the right, 60; 60 is copied into the root and the old 60 (only child: 65) is deleted → 65 becomes 70's left child.
35404560657080

Inorder: 35 40 45 60 65 70 80

Multiple Choice · BST Operations

Question 9: The Successor's Children

Deleting a node with two children copies in its inorder successor, then deletes the successor itself. Why is that second deletion always a leaf or one-child case?

minValue goes left until a node has no left child. The successor may have a right child (B and D are wrong) and may sit deeper down (C is wrong). Symmetrically, the predecessor has no right child.

Code Trace · BST Operations

Question 10: Tracing range()

In the tree shown, what does range(root, 38, 62) print, and which nodes are never visited?

20303540455060657080
20303540455060657080

38 < 50 → there may be keys in range on the left: go left.

20303540455060657080

38 < 30 is false → the left subtree (20) is pruned. 30 is out of range. 30 < 62 → go right.

20303540455060657080

38 < 40 → go left.

20303540455060657080

35: left pruned, out of range; 35 < 62 → go right (null), returns at once.

20303540455060657080

Back at 40: 40 ∈ [38, 62] → print.

20303540455060657080

40 < 62 → go right: 45. Left empty; 45 in range → print. Right empty too.

20303540455060657080

The frames for 45, 40, and 30 close; back at 50: 50 is in range → print.

20303540455060657080

50 < 62 → go right: 70. 38 < 70 → go left.

20303540455060657080

60: its left is empty; 60 is in range → print. 60 < 62 → go right.

20303540455060657080

65 is out of range; 65 < 62 is false → its right is pruned.

20303540455060657080

Back at 70: out of range; 70 < 62 is false → 80 is pruned.

20303540455060657080

The output is sorted: 40 45 50 60. 20 and 80 were never visited → O(h + s).

void range(TreeNode k, int lo, int hi) {
    if (k == null) return;
    if (lo < k.data)           // candidates on the left
        range(k.left, lo, hi);
    if (lo <= k.data && k.data <= hi)
        System.out.print(k.data + " ");
    if (k.data < hi)           // candidates on the right
        range(k.right, lo, hi);
}

Multiple Choice · Balance and AVL Trees

Question 11: An Order for a Perfect Tree

In which order should the keys 1, 2, …, 7 be inserted into an empty BST to get a (perfect) tree of height 2?

The middle first (4), then each half's middle (2, 6), the leaves last. In B, 1–2–3 and 5–6–7 become chains (h = 3); in C the root 2 leaves the right side heavy (h = 3); A is a chain with h = 6. A BST's shape depends on the insertion order.

Short Answer · Balance and AVL Trees

Question 12: Balance Factor and Rotation

The figure shows an AVL tree just after inserting 27, before rebalancing. Compute the balance factors, decide which rotation goes at which node, and draw the result.

101517202527304050
Show answer

bf = h(left) − h(right), with −1 for an empty subtree. From 27 up to the root: bf(25) = −1, bf(20) = 0 − 1 = −1, bf(15) = 0 − 2 = −2 ✗, bf(30) = 3 − 1 = 2 ✗.

Fix the lowest unbalanced node, 15: right-heavy, with right child 20 at bf = −1 (same direction) → RR: a left rotation at 15.

101517202527304050

The subtree's height returns to 2, so 30 is balanced again too (bf = 1).

Multiple Choice · Balance and AVL Trees

Question 13: Which Rotation?

Insert 50, 20, 30 in that order into an empty AVL tree. Which case arises, and how is the tree rebalanced?

bf(50) = 2 (left-heavy), but the left child 20 has bf = −1 (leaning right): a zigzag (triangle) → LR. A single right rotation (A) gives 20(—, 50(30, —)) with bf(20) = −2, still unbalanced. The correct result is 30(20, 50).

Short Answer · Balance and AVL Trees

Question 14: A Sequence of AVL Insertions

Insert 40, 20, 10, 25, 30, 22, 50 in that order into an empty AVL tree. Name the case (LL, RR, LR, RL) and the rotations for each imbalance, and draw the final tree.

Show answer
  • +10: bf(40) = 2, bf(20) = 1 → LL: right at 40 → 20(10, 40).
  • +25: left of 40; no imbalance.
  • +30: right of 25; bf(40) = 2, bf(25) = −1 → LR: left at 25, right at 40 → 20(10, 30(25, 40)).
  • +22: left of 25; bf(20) = −2, bf(30) = 1 → RL: right at 30, left at 20 → 25(20(10, 22), 30(—, 40)).
  • +50: bf(30) = −2, bf(40) = −1 → RR: left at 30.
10202225304050

The final tree: all four cases appeared along the way; h = 2.

Multiple Choice · Red-Black Trees

Question 15: Which Rule Is Broken?

In the figure, the dark nodes are black and 40 is red; empty children (NIL) count as black. Which red-black tree rule does this tree break?

1020253040

20 → 10 → NIL has 2 blacks (20, 10), but 20 → 30 → 25 → NIL has 3 (20, 30, 25). The only red node, 40, has NIL (black) children, and the root is black. Making 25 red gives every path 2 blacks, and the tree becomes valid.

Short Answer · Red-Black Trees

Question 16: Inserting into a Red-Black Tree

Insert 50, 40, 30, 35, 45, 32 in that order into an empty red-black tree. Name the case for each insertion that needs fixing, and draw the final tree with colors.

Show answer
  • 50: the root → black. 40: the parent is black, nothing to do.
  • 30: parent 40 is red, the uncle is NIL (black), and 30–40–50 is a line → rotate right at 50; 40 black, 50 red.
  • 35: parent 30 and uncle 50 are red → recolor: 30 and 50 black, 40 red; 40 is the root, so it turns black again.
  • 45: parent 50 is black, nothing to do.
  • 32: parent 35 is red, the uncle is NIL; 32–35–30 is a triangle → rotate right at 35 (a line), then left at 30; 32 black, 30 red.
303235404550

Every path has 2 black nodes, and no two reds are adjacent.

Multiple Choice · Red-Black Trees

Question 17: AVL or Red-Black?

Which choice suits a large, rarely updated dictionary in which 95% of operations are searches?

Both give O(log n), but AVL builds a shorter tree, and its costlier updates (O(log n) rotations on deletion) hardly matter when updates are rare. A has it backwards: red-black trees are balanced more loosely; their cheap updates (≤ 2–3 rotations, 1 color bit) make them the choice for frequently updated structures and libraries (TreeMap, std::map).

Code Trace · Splay Trees

Question 18: Tracing splay()

In the splay tree shown, we access 10. What steps does splay(10) take, and what is the final tree?

102030405060
102030405060

x is not the root. p = 20, g = 30.

102030405060

g exists, and x and p are both left children → same side: zig-zig.

102030405060

The grandparent first: rotate right at 30 → 20 moves up.

102030405060

Then the parent: rotate right at 20 → x has risen two levels.

102030405060

x is still not the root. p = 50 is the root, g = null.

102030405060

g == null → zig: rotate right at 50; 10 becomes the root, and its old right subtree (20…) becomes 50's left.

102030405060

x == root → the loop ends. A zig comes only as the last step; a zig-zig rotates the grandparent first.

void splay(Node x) {
    while (x != root) {
        Node p = x.parent, g = p.parent;
        if (g == null)  // zig
            rotate(p, x);
        else if (sameSide(x, p, g)) {
            rotate(g, p); // grandparent first
            rotate(p, x);
        } else { // zig-zag
            rotate(p, x);
            rotate(g, x);
        }
    }
}

Short Answer · Multiway Search Trees

Question 19: B-Tree Insertion

Insert 40, 10, 30, 20, 50, 60, 70, 80 in that order into an empty B-tree of order m = 3 (at most 2 keys per node). Draw the final tree. How many times does the root split?

Show answer
  • 30: [10 30 40] overflows → median 30 is the new root over [10] and [40] (root split 1).
  • 20 → [10 20]; 50 → [40 50]; 60: [40 50 60] overflows → 50 moves up: root [30 50].
  • 70 → [60 70]; 80: [60 70 80] overflows → 70 moves up, root [30 50 70] overflows → 50 is the new root (root split 2).
50307010 20406080

The root split twice; the height grew only on root splits, and all leaves stayed at the same depth. A B-tree grows upward.

Multiple Choice · Multiway Search Trees

Question 20: Range Queries in a B+ Tree

A database index serves frequent range queries such as “between 20 and 50.” Which property makes a B+ tree better than a B-tree for this job?

D. The leaf holding the lower bound 20 is found in O(log n); then the leaf chain is followed without climbing back up: O(log n + k) in total, k = number of results. A describes a B-tree; in a B+ tree internal nodes hold only routing keys, so more keys fit in a block and the tree is shallower.

Open-Ended Question · Summary

Question 21: A Dictionary App

A dictionary app must add words, look words up, and list all words starting with "ab" alphabetically; at setup, the words are bulk-loaded in alphabetical order. Would you pick a HashMap, a plain BST, or a TreeMap (a red-black tree)? Justify.

Sample answer

A HashMap gives O(1) average insertion and lookup but keeps no order; a prefix query must scan the whole table and sort the result (O(n + k log k)).

A plain BST is ordered, but alphabetical loading puts each word right of the previous: a chain, h = n − 1, O(n²) to load, O(n) per operation.

A TreeMap keeps keys sorted and uses rotations to guarantee h = O(log n), so sorted loading is fine. A prefix query is a range query: subMap("ab", "ac") takes O(log n + k) and returns the words already sorted. For prefix-heavy work, a specialized structure (a trie) is also worth considering.

Short Answer · Balance and AVL Trees

Question 22: A Chain of AVL Fixes After Deletion

Delete 60 from the AVL tree shown. The course's delete does a BST deletion, then calls rebalance at each ancestor as the recursion unwinds. Which rotations happen at which nodes on the way up? Draw the final tree.

51015202530354045505560
Show answer

bf = h(left) − h(right), with −1 for an empty subtree.

  • 60 is a leaf → it is cut off. 55: bf = 1 − (−1) = 2 ✗, bf(50) = 1 → LL: right at 55 → 50(45, 55). This subtree's height drops from 2 to 1.
  • 40: bf = 3 − 1 = 2 ✗, bf(15) = 1 − 2 = −1 → LR: left at 15 (30 moves up), then right at 40.
510152025303540455055

3 rotations at two ancestors; the height drops from 4 to 3. An insertion needs one fix, but in a deletion a rotation can shorten a subtree and push the imbalance upward: rotations at up to O(log n) ancestors.

Multiple Choice · Balance and AVL Trees

Question 23: A Child with bf = 0 on Deletion

We delete 60 from the AVL tree 50(30(20, 40), 60). What does the call to rebalance at 50 do?

if (bf(d) > 1) {        // left-heavy
    if (bf(d.left) < 0)   // LR
        d.left = rotateLeft(d.left);
    return rotateRight(d);  // LL
}

B: with 60 gone, bf(50) = 1 − (−1) = 2, and the left child 30 has bf = 0. This arises only on deletion, never on insertion; bf(d.left) < 0 is false, so the code does a single right rotation, and 40 moves from 30's right to 50's left. A would also give a balanced tree (40(30(20, —), 50)), but the code does no double rotation here. C: bf = 2 is a violation. D: the height stays 2, as before the deletion.

The End

Chapter 10: Search Trees: Study Questions
Lecture slides: Chapter 10: Search Trees
1 / 1 Sercan KÜLCÜ. All rights reserved.