The are plenty of examples of AVL rotations in books and on the internet, but what I found seemed arbitrary and no one place seemed to include simple examples for all 4 cases for insert and delete.
These are the simplest test case I could come up with for the 4 kinds of rotations. To make it easy to describe, I’ve used ascii characters as the key so a test case can be expressed as a string. For example, the string "abc" would be insert "a", insert "b" and then insert "c".
The full test cases create some pretty complicated trees so I’ve created two test suites. The first causes the rotations, but has empty sub-trees for the nodes being rotated making it easy to see what actually happened. The second suite has non-empty sub-trees to fully test the rotation code.
There seem to be two different nomanclature for rotates - what I learned as a 2L rotation, some books call an rl rotation and the 2R rotation is call an lr rotation. The text below uses 2R/2L.
These are the simple test cases for insert
"abc", on the insert of "c" will require a 1L rotation
a b
\ / \
b == 1L ==> a c
\
c
“cba”, on the insert of “a” will require a 1R rotation
c b
/ / \
b == 1R ==> a c
/
a
"acb" on the insert of "b" will require a 2L rotation
a b
\ / \
c == 2L ==> a c
/
b
“cab” on the insert of “b” will require a 2R rotation
c b
/ / \
a == 2R ==> a c
\
b
For delete
“bcad”, on the deletion of “a” will require a 1L rotation
b c
x \ / \
a c == 1L ==> b d
\
d
“cbda”, on the deletion of “d” will require a 1R rotation
c b
/ x / \
b d == 1R ==> a c
/
a
“bdac” on the deletion of “a” will require a 2L rotation
b c
x \ / \
a d == 2L ==> b d
/
c
“cadb” on the deletion of “d” will require a 2R rotation
c b
/ x / \
a d == 2R ==> a c
\
b
The more complex test cases have sub-trees, most just being a single node. To make this post shorter, the insert and delete test cases are combined. The delete example becomes the insert example by skipping the insertion of the delete character. For example, using the 2R simple delete case above “cadb” becomes the insert case “cab” by skipping the insert of “d”. One consequence of this is the double rotate cases below require inserting an extra node to keep the tree balanced after inserting the node to be deleted. This results in the insert case not being minimal.
“cbedfag” on the delete of “a” or skipping “a” and the insert of “g” will require a 1L rotation at c
c e
/ \ / \
b e == 1R ==> c f
x / \ / \ \
a d f b d g
\
g
“ecfbdga” on the delete of “g” or skipping “g” and the insert of “a” will require a 1R rotation at e
- e - c
/ \ / \
c f == 1R ==> b e
/ \ x / / \
b d g a d f
/
a
“ecjadhkgilbf” on the delete of “b” or skipping “b” and the insert of “f” will require a 2L rotation at j then e. The insert case can optionally skip inserting “d”.
- e - —- h —-
/ \ / \
c j - e- j
/ \ / \ == 2L ==> / \ / \
a d h k c g i k
x / \ \ / \ / \
b g i l a d f l
/
f
“hckbeiladfjg” on the delete of “j” or skipping “j” and the insert of “g” will require a 2R rotation at c then b. The insert case can optionally skip inserting “l”
- h - - e -
/ \ / \
c k c - h -
/ \ / \ == 2R ==> / \ / \
b e i l b d f k
/ / \ x / \ / \
a d f j a g i l
\
g
Use methods 1 and 2 from the question to verify the tree rebalanced as required (ie, verify tree is still in order and balanced). If you wanted to be really sure, convert the visual test cases to include a list of depth and balance values of the final tree to verify during an inorder traversal.