DECMATRIX

Mathematical Tools

Interactive AVL Tree Exercises

Complete exercise

Build the tree by inserting each value in its correct position and manually performing every rebalance. This exercise has its own settings and counters.

Configure or restart
Next exercise settings

Quick rotation practice

Balance a prebuilt tree with one or two rotations. After solving it, inspect the corrected tree and choose Next exercise to generate another challenge. This practice is independent of the complete exercise above.

Balance this tree

One simple rotation

Preparing a one-rotation challenge…

Want to experiment freely? Open the AVL tree simulator.

How to practice

Choose what to practice. In Quick rotation practice, the tree is already built: your task is to balance it. In the Complete exercise, open Configure or restart, select a mode and 6 to 20 values (the default is 8), then choose Start exercise. Mixed includes at least two case types; LL, RR, LR and RL modes guarantee the chosen case and may include others.

In the complete exercise, read the current value and use Insert at root for the first node. For later values, walk down the tree comparing with every ancestor. Select the parent by clicking a node or using the Select node list, then choose Insert on the left or Insert on the right. The position must be empty and respect every bound along the path. An incorrect attempt preserves the tree and current value while explaining the mistake.

After each valid insertion, check whether rebalancing is required. Help and hints lets you display balance factors and reveal progressive clues. Start at the newly inserted value, follow its parents upward, and stop at the first ancestor with factor +2 or −2. The path from that ancestor identifies LL, RR, LR or RL; the case name is not the direction of the rotation button.

Select the node for the next operation and choose Rotate left or Rotate right. Each click performs just one simple rotation. For LR and RL, first rotate the corresponding child, then the original ancestor: the still-unbalanced intermediate state is part of the solution. The next value is unlocked only when BST order, heights and balance are correct. The student's tree never repairs itself automatically.

Use zoom, panning and Fit to view to inspect nodes; the list lets you select a node even when it is outside the frame. Footer indicators track correct actions, errors, rotations and hints without a collapsed panel. When finished, review your score and retry or generate a new exercise. In quick practice, the corrected tree stays visible until you choose Next exercise; doing so does not restart the complete exercise.

A position must respect every ancestor

A binary search tree (BST) does not compare a node only with its parent. Every value in an ancestor's left subtree must be smaller than that ancestor; every value in its right subtree must be larger. As you move down the tree, those comparisons accumulate an allowed interval for the new position.

Consider 30 at the root and 20 to its left. To insert 25 to the right of 20, it must be larger than 20 and smaller than 30: both conditions hold. Although 35 is also larger than 20, it cannot occupy that position because it would still be inside 30's left subtree. The correct path for 35 starts to the right of 30.

In the tool, selecting 20 and choosing Insert on the right is valid only when the current value lies in 20 < value < 30. If an attempt violates a bound, feedback identifies the responsible ancestor and preserves the tree. Trace the path from the root again before choosing another parent or side; a later rotation must not be used to try to repair an invalid BST insertion.

Height and balance factor

A leaf has height 0; an empty subtree has height −1. The factor is height(left) − height(right). A valid AVL tree has factors −1, 0 or +1 at every node. After insertion, move up to the first unbalanced ancestor. The student's tree never fixes itself automatically.

For example, a node with a left leaf and no right child has height 1 and balance factor 0 − (−1) = +1. If its left subtree grows to height 1 while the right side stays empty, the factor becomes 1 − (−1) = +2: rebalancing is needed.

Find the first unbalanced ancestor

  1. Start at the newly inserted value and follow its parents upward.
  2. At each node, compare the left and right heights. Factors −1, 0 and +1 are valid.
  3. Stop at the first node with factor +2 or −2. Identify the case using the factor of the child on the taller side too.
  4. Perform the simple rotation or both operations of a double rotation. Resume insertion only after checking the entire tree.

LL, RR, LR and RL

  • LL: the extra height is on the left of the left child. Rotate the unbalanced ancestor right.
  • RR: the extra height is on the right of the right child. Rotate the unbalanced ancestor left.
  • LR: rotate the left child left, then rotate the ancestor right.
  • RL: rotate the right child right, then rotate the ancestor left.

L means left and R means right. Starting at the first unbalanced ancestor, the first letter identifies the taller child's side; the second identifies the side that grew within that child. The name describes the imbalance path, not the direction of the corrective rotation. LL is fixed by rotating right, RR by rotating left; LR and RL require two operations. In the diagrams, a dashed ring identifies the node for the next rotation, also named in the caption.

Worked examples, one operation at a time

LL: 30, 20, 10

  1. Insert 30 at the root, 20 to its left, then 10 to the left of 20. Moving up from 10, node 20 has factor +1; the first invalid ancestor is 30, with factor +2.
  2. From 30 to the inserted value, the path goes left, then left: LL. The extra height is on the outer side, so one rotation is enough. Select 30 and choose Rotate right, not Rotate left.
  3. Node 20 rises to the root, 10 stays on the left, and 30 becomes 20's right child. The order 10 < 20 < 30 is preserved and all three factors become 0. The complete exercise can now unlock the next value.
1. Before

Next action: rotate right at node 30 (dashed ring).

302010

Node 30: left child 20; right child empty. Node 20: left child 10; right child empty. Node 10: left child empty; right child empty.

2. After

Balanced tree: root 20, children 10 and 30. Every factor is 0.

302010

Node 30: left child empty; right child empty. Node 20: left child 10; right child 30. Node 10: left child empty; right child empty.

RR: 10, 20, 30

  1. Insert 10 at the root, 20 to its right, then 30 to the right of 20. Moving up from 30, node 20 has factor −1; the first unbalanced ancestor is 10, with factor −2.
  2. The path from 10 goes right, then right: RR. Although both letters say right, the corrective operation is a left rotation. Select 10 and choose Rotate left.
  3. Node 20 becomes the root, with 10 on the left and 30 on the right. No value changes or disappears; only links are rearranged. All three factors become 0.
1. Before

Next action: rotate left at node 10 (dashed ring).

102030

Node 10: left child empty; right child 20. Node 20: left child empty; right child 30. Node 30: left child empty; right child empty.

2. After

Balanced tree: root 20, children 10 and 30. Every factor is 0.

102030

Node 10: left child empty; right child empty. Node 20: left child 10; right child 30. Node 30: left child empty; right child empty.

LR: 30, 10, 20

  1. Insert 30 at the root, 10 to its left, then 20 to the right of 10. Moving up from 20, node 10 has factor −1; the first unbalanced ancestor is 30, with factor +2. The path from 30 goes left, then right: LR.
  2. The growth is on the inner side. Select 10 and choose Rotate left. In the intermediate state, 20 becomes 30's left child and 10 sits to the left of 20. Node 30 still has factor +2: this is expected, not a failed first operation.
  3. Select the original ancestor, 30, and choose Rotate right. Now 20 is the root, with children 10 and 30 and factors 0. These are two separate actions; do not try to insert the next value between them.
1. Before

Next action: rotate left at node 10 (dashed ring).

301020

Node 30: left child 10; right child empty. Node 10: left child empty; right child 20. Node 20: left child empty; right child empty.

2. After the first rotation

Next action: rotate right at node 30 (dashed ring).

301020

Node 30: left child 20; right child empty. Node 10: left child empty; right child empty. Node 20: left child 10; right child empty.

3. After

Balanced tree: root 20, children 10 and 30. Every factor is 0.

302010

Node 30: left child empty; right child empty. Node 20: left child 10; right child 30. Node 10: left child empty; right child empty.

RL: 10, 30, 20

  1. Insert 10 at the root, 30 to its right, then 20 to the left of 30. Moving up from 20, node 30 has factor +1; the first unbalanced ancestor is 10, with factor −2. The path from 10 goes right, then left: RL.
  2. First select child 30 and choose Rotate right. In the intermediate state, 20 becomes 10's right child and 30 sits to the right of 20. Node 10 still has factor −2 because the original ancestor has not yet been fixed.
  3. Select 10 and choose Rotate left. The final root is 20, with 10 on the left and 30 on the right; all factors become 0. This mirrors LR, with the directions of both operations reversed.
1. Before

Next action: rotate right at node 30 (dashed ring).

103020

Node 10: left child empty; right child 30. Node 30: left child 20; right child empty. Node 20: left child empty; right child empty.

2. After the first rotation

Next action: rotate left at node 10 (dashed ring).

103020

Node 10: left child empty; right child 20. Node 30: left child empty; right child empty. Node 20: left child empty; right child 30.

3. After

Balanced tree: root 20, children 10 and 30. Every factor is 0.

102030

Node 10: left child empty; right child empty. Node 20: left child 10; right child 30. Node 30: left child empty; right child empty.

Common mistakes and how to fix them

  • Comparing only with the parent: check all ancestor bounds too.
  • Always rotating the root: start at the first unbalanced ancestor, which may be inside the tree.
  • Reading LL as rotate left: the name describes the path; the rotation opposes the outer imbalance.
  • Stopping after the first LR/RL operation: check the original ancestor and perform the second rotation.
  • Attempting a rotation without the required child: a left rotation needs a right child, and a right rotation needs a left child.

FAQ

Decmatrix - Your open-source mathematical toolkit for calculations, conversions, and more.
Terms of Use
Privacy Policy
Contact: decimatrix25@gmail.com