@@ -306,60 +306,112 @@ class AvlTree<V extends Comparable> extends BinaryTreeADT<AvlNode<V>, V> {
306306 // Right subtree of [node]
307307 var rChild = node.right;
308308
309- // [rChild] was balanced.
310- // N
311- // \
312- // R
313- // / \
314- // ** **
315- if (rChild! .balanceFactor == 0 ) {
316- // Single left rotation about [node] is performed to balance it.
317- node = _rotateLeft (node);
309+ switch (rChild! .balanceFactor) {
318310
319- node.balanceFactor = - 1 ;
320- rChild.balanceFactor = 1 ;
321- _isShorter = false ;
322- }
311+ // [rChild] was balanced, single left rotation about [node] is performed
312+ // to balance the [node].
313+ case 0 :
314+ //
315+ // N N R
316+ // / \ /↶\ / \
317+ // ...█...R.... ⟶ h ...█...R.... ⟶ ....N...█...
318+ // h+1 ...▒../.\... ....../.\... .../.\..█.. h+1
319+ // .....█...█.. .....█...█.. h ..█...█.....
320+ // h+1 ..█...█.. h+1 h+1 ..█...█.. h+1 ......█.. h+1
321+ //
322+ node = _rotateLeft (node);
323323
324- // [rChild] was right heavy.
325- // N
326- // \
327- // R
328- // / \
329- // * **
330- else if (rChild.balanceFactor == - 1 ) {
331- node.balanceFactor = rChild.balanceFactor = 0 ;
332- // Single left rotation about [node] is performed to balance it.
333- node = _rotateLeft (node);
334- }
324+ node.balanceFactor = - 1 ;
325+ rChild.balanceFactor = 1 ;
335326
336- // [rChild] was left heavy.
337- else {
338- // Left subtree of [rChild].
339- var lGrandChild = rChild.left;
340- switch (lGrandChild! .balanceFactor) {
327+ // Height of the subtree rooted at N does not change, hence [_isShorter]
328+ // is made `false`.
329+ _isShorter = false ;
330+ break ;
341331
342- // [lGrandChild] was balanced.
343- case 0 :
344- node.balanceFactor = rChild.balanceFactor = 0 ;
345- break ;
332+ // [rChild] was right heavy, single left rotation about [node] is
333+ // performed to balance the [node].
334+ case - 1 :
335+ //
336+ // N N R
337+ // / \ /↶\ / \
338+ // ...█...R.... ⟶ h ...█...R.... ⟶ ....N...█...
339+ // h+1 ...▒../.\... ....../.\... .../.\..█.. h+1
340+ // .....█...█.. .. h █...█.. h ..█...█.....
341+ // ... h ...█.. h+1 .........█.. h+1 ...... h ...
342+ //
343+ node = _rotateLeft (node);
346344
347- // [lGrandChild] was left heavy.
348- case 1 :
349- node.balanceFactor = 0 ;
350- rChild.balanceFactor = - 1 ;
351- break ;
345+ node.balanceFactor = rChild.balanceFactor = 0 ;
352346
353- // [lGrandChild] was right heavy.
354- case - 1 :
355- node.balanceFactor = 1 ;
356- rChild.balanceFactor = 0 ;
357- break ;
358- }
359- lGrandChild.balanceFactor = 0 ;
360- // Right Left rotation is perfomed to balance [node].
361- node.right = _rotateRight (rChild);
362- node = _rotateLeft (node);
347+ // Height of the subtree rooted at N has changed, hence [_isShorter]
348+ // remains `true`.
349+ break ;
350+
351+ // [rChild] was left heavy. In this case, a single rotation will not
352+ // suffice so double rotation is performed. L is the root
353+ // node of [rChild]'s left subtree.
354+ //
355+ // N N
356+ // / \ / \
357+ // ...█...R.... ...█...R....
358+ // h+1 ...▒../.\... h+1 ...▒. /.\...
359+ // .....█...█.. h .... L ..█.. h
360+ // .h+1 █...... / \
361+ //
362+ case 1 :
363+
364+ // Left subtree of [rChild].
365+ var lGrandChild = rChild.left;
366+
367+ switch (lGrandChild! .balanceFactor) {
368+
369+ // [lGrandChild] was balanced.
370+ case 0 :
371+ // N N N
372+ // / \ / \ /↶\ L
373+ // ...█...R.... h ...█...R.... h ...█...L...... / \
374+ // h+1 ...▒. /.\... ⟶ ..... /↷\... ⟶ ....../.\..... ⟶ N R
375+ // .... L ..█.. h .... L ..█.. h h..█...R.... / \ / \
376+ // / \ / \ ...../.\... h..█...█.█...█..h
377+ // h ..█...█.. h h ..█...█.. h h..█...█.. h
378+ //
379+ node.balanceFactor = rChild.balanceFactor = 0 ;
380+ break ;
381+
382+ // [lGrandChild] was left heavy.
383+ case 1 :
384+ // N N N
385+ // / \ / \ /↶\ L
386+ // ...█...R.... h ...█...R.... h ...█...L...... / \
387+ // h+1 ...▒. /.\... ⟶ ..... /↷\... ⟶ ....../.\..... ⟶ N R
388+ // .... L ..█.. h .... L ..█.. h h..█...R.... / \ / \
389+ // / \ / \ ...../.\... h..█...█ ▀ █..h
390+ // h ..█...▀.. h-1 h ..█...▀.. h-1 h-1..▀...█.. h │
391+ // h-1 ┘
392+ node.balanceFactor = 0 ;
393+ rChild.balanceFactor = - 1 ;
394+ break ;
395+
396+ // [lGrandChild] was right heavy.
397+ case - 1 :
398+ // N N N
399+ // / \ / \ /↶\ L
400+ // ...█...R.... h ...█...R.... h ...█...L...... / \
401+ // h+1 ...▒. /.\... ⟶ ..... /↷\... ⟶ ....../.\..... ⟶ N R
402+ // .... L ..█.. h .... L ..█.. h h-1..▀...R.... / \ / \
403+ // / \ / \ ...../.\... h..█ ▀ █...█..h
404+ // h-1 ..▀...█.. h h-1 ..▀...█.. h h..█...█.. h │
405+ // h-1 ┘
406+ node.balanceFactor = 1 ;
407+ rChild.balanceFactor = 0 ;
408+ break ;
409+ }
410+ lGrandChild.balanceFactor = 0 ;
411+ // Right Left rotation is perfomed to balance [node].
412+ node.right = _rotateRight (rChild);
413+ node = _rotateLeft (node);
414+ break ;
363415 }
364416 return node;
365417 }
@@ -451,47 +503,47 @@ class AvlTree<V extends Comparable> extends BinaryTreeADT<AvlNode<V>, V> {
451503 }
452504
453505 /// Updates [balanceFactor] of the [node] when deletion is done from it's left
454- /// subtree.\
506+ /// subtree.
455507 AvlNode <V > _dUpdateLeftBalanceFactor (AvlNode <V > node) {
456508 switch (node.balanceFactor) {
457509
458- // [node] was balanced before deletion. (Both left and right subtree had
459- // the same height.)
460- // N
461- // / \
462- // ** **
510+ // [node] was balanced before deletion, is right heavy now.
463511 case 0 :
464- // [node] is right heavy now.
465- // N
466- // / \
467- // * **
512+ // N N
513+ // / \ ⟶ / \
514+ // ...█...█... h ...█...█...
515+ // h+1 ...▒...█... h+1 .......█... h+1
516+ //
468517 node.balanceFactor = - 1 ;
518+
519+ // Balance factors of the ancestors of this [node] will remain
520+ // unchanged (since height of the subtree rooted at N didn't change).
521+ // Therefore [_isShorter] is set to `false`.
469522 _isShorter = false ;
470523 break ;
471524
472- // [node] was left heavy before deletion. (Left subtree's height was one
473- // more than that of right subtree.)
474- // N
475- // / \
476- // ** *
525+ // [node] was left heavy before deletion, is balanced now.
477526 case 1 :
478- // [node] is balanced now.
479- // N
480- // / \
481- // * *
527+ // N N
528+ // / \ ⟶ / \
529+ // ...█...█... h h ...█...█... h
530+ // h+1 ...▒....... ...........
531+ //
482532 node.balanceFactor = 0 ;
533+
534+ // Height of the subtree rooted at N has decreased, [_isShorter] remains
535+ // `true`.
483536 break ;
484537
485- // [node] was right heavy before deletion. (Right subtree's height was one
486- // more than that of left subtree.)
487- // N
488- // / \
489- // * **
538+ // [node] was right heavy before deletion, is imbalanced now, has to be
539+ // balanced.
490540 case - 1 :
491- // [node] is imbalanced now, has to be balanced.
492- // N
493- // \
494- // **
541+ // N N
542+ // / \ / \
543+ // ...█...█... ⟶ h-1 ...█...█...
544+ // h ...▒...█... .......█...
545+ // .......█... h+1 .......█... h+1
546+ //
495547 node = _dBalanceRightHeavy (node);
496548 }
497549 return node;
0 commit comments