E- mail: bradapp@enteract.com WWW: www.enteract.com/~bradapp/ AVL Trees: Tutorial and C++ Implementation Copyright 1989-1997 by Brad Appleton All right! re!er"ed. #he $ollowing di!c%!!ion i! part o$ a $reely a"ailable p%blic domain A&' tree library written in C((. #he $%ll C(( !o%rce code di!trib%tion may be $o%nd in AvlTrees.tar.gz )*1+B g,ipped tar $ile-. .a plain old +/0 C "er!ion i! a"ailable in libavl.tar.gz )*1+B g,ipped tar $ile-2 AVL Trees An A&' tree i! a !pecial type o$ binary tree that i! alway! 3partially3 balanced. #he criteria that i! %!ed to determine the 3le"el3 o$ 3balanced-ne!!3 i! the di$$erence between the height! o$ !%btree! o$ a root in the tree. #he 3height3 o$ tree i! the 3n%mber o$ le"el!3 in the tree. 4r to be more $ormal the height o$ a tree i! de$ined a! $ollow!5 1. #he height o$ a tree with no element! i! 6 *. #he height o$ a tree with 1 element i! 1 7. #he height o$ a tree with 8 1 element i! e9%al to 1 ( the height o$ it! talle!t !%btree. An A&' tree i! a binary tree in which the di$$erence between the height o$ the right and le$t !%btree! )or the root node- i! ne"er more than one. #he idea behind maintaining the 3A&'-ne!!3 o$ an A&' tree i! that whene"er we in!ert or delete an item i$ we ha"e 3"iolated3 the 3A&'-ne!!3 o$ the tree in anyway we m%!t then re!tore it by per$orming a !et o$ manip%lation! )called 3rotation!3- on the tree. #he!e rotation! come in two $la"or!5 !ingle rotation! and do%ble rotation! )and each $la"or ha! it! corre!ponding 3le$t3 and 3right3 "er!ion!-. An e:ample o$ a !ingle rotation i! a! $ollow!5 ;%ppo!e < ha"e a tree that loo=! li=e thi!5 c / b >ow < in!ert the item 3a3 and get the re!%lting binary tree5 c / b / a >ow thi! re!%lting tree "iolate! the 3A&' criteria3 the le$t !%btree ha! a height o$ * b%t the right !%btree ha! a height o$ 6 !o the di$$erence in the two height! i! 3*3 )which i! greater than 1-. ;4 what we do i! per$orm a 3!ingle rotation3 )or 00 $or a !ingle right rotation or '' $or a !ingle le$t rotation- on the tree )by rotating the 3c3 element down cloc=wi!e to the right- to tran!$orm it into the $ollowing tree5 b / \ a c #hi! tree i! now balanced. An e:ample o$ a 3do%ble rotation3 )or 0' $or a do%ble right rotation or '0 $or a do%ble le$t rotation- i! the $ollowing5 ;%ppo!e < ha"e a tree that loo=! li=e thi!5 a \ c >ow < in!ert the item 3b3 and get the re!%lting binary tree5 a \ c / b #hi! re!%lting tree al!o "iolate! the 3A&' criteria3 !o we $i: it by $ir!t rotating 3c3 down to the right )!o we get 3a-b-c3- and then rotating 3a3 down to the le$t !o that the tree i! tran!$ormed into thi!5 b / \ a c <n order to detect when a 3"iolation3 o$ the A&' criteria occ%r! we need to ha"e each node =eep trac= o$ the di$$erence in height between it! right and le$t !%btree!. ?e call thi! 3di$$erence3 the 3balance3 $actor and de$ine it to be the height o$ the right !%btree min%! the height o$ the le$t !%btree o$ a tree. ;o a! long a! the 3balance3 $actor o$ each node i! ne"er 81 or @-1 we ha"e an A&' tree. A! !oon a! the balance $actor o$ a node become! * )or -*- we need to per$orm one or more rotation! to en!%re that the re!%ltant tree !ati!$ie! the A&' criteria. Implementing AVL Trees in C++ Be$ore we begin o%r A&' tree implementation in C(( let! a!!%me we ha"e a template cla!! named 3Comparable3 de$ined a! $ollow!5 // cmp_t is an enumeration type indicating the result of a // comparison. enum cmp_t { MI_!M" # $%& // less than '(_!M" # )& // e*ual to MA+_!M" # % // greater than ,- // !lass .!omparable. corresponds to an arbitrary comparable element // /ith a 0eyfield that has an ordering relation. The template parameter // 1eyType is the .type. of the 0eyfield // template 2class 1eyType3 class !omparable { private4 1eyType my1ey- public4 !omparable51eyType 0ey6 4 my1ey50ey6 {,- // 7se default copy$ctor& assignment& 8 destructor // !ompare this item against the given 0ey 8 return the result cmp_t !ompare51eyType 0ey6 const- // 9et the 0ey$field of an item 1eyType 1ey56 const { return my1ey- , ,- 'i=e the 3Comparable3 cla!! o%r A&' tree will al!o be a template cla!! parameteri,ed by a +ey#ype5 // !lass Avlode represents a node in an A:; tree. The template parameter // 1eyType is the .type. of the 0eyfield // template 2class 1eyType3 class Avlode { private4 !omparable21eyType3 < my=ata- // =ata field Avlode21eyType3 < my>ubtree?@A- // >ubtree pointers short myBal- // Balance factor // ... many details omitted ,- Calculating New Balances After a Rotation #o calc%late the new balance! a$ter a !ingle le$t rotationA a!!%me we ha"e the $ollowing ca!e5 A B / \ / \ / \ / \ a B ##3 A c / \ / \ / \ / \ b c a b #he le$t i! what the tree loo=ed li=e BBC40B the rotation and the right i! what the tree loo=! li=e a$ter the rotation. Capital letter! are %!ed to denote !ingle node! and lowerca!e letter! are %!ed to denote !%btree!. #he 3balance3 o$ a tree i! the height o$ it! right !%btree le!! the height o$ it! le$t !%btree. #here$ore we can calc%late the new balance! o$ 3A3 and 3B3 a! $ollow! )ht i! the height $%nction-5 e/Bal5A6 # ht5b6 $ ht5a6 CldBal5A6 # ht5B6 $ ht5a6 # 5 % D maE 5ht5b6& ht5c66 6 $ ht5a6 !%btracting the !econd e9%ation $rom the $ir!t yield!5 e/Bal5A6 $ CldBal5A6 # ht5b6 $ 5 % D maE 5ht5b6& ht5c66 6 D ht5a6 $ ht5a6 canceling o%t the ht)a- term! and adding 4ldBal)A- to both !ide! yield!5 e/Bal5A6 # CldBal5A6 $ % $ 5maE 5ht5b6& ht5c66 $ ht5b6 6 >oting that ma:): y- - , D ma:):-, y-,- we get5 e/Bal5A6 # CldBal5A6 $ % $ 5maE 5ht5b6 $ ht5b6& ht5c6 $ ht5b66 6 B%t ht)c- - ht)b- i! 4ldBal)B- !o we get5 e/Bal5A6 # CldBal5A6 $ % $ 5maE 5)& CldBal5B66 6 # CldBal5A6 $ % $ maE 5)& CldBal5B66 #h%! $or A we get the e9%ation5 e/Bal5A6 # CldBal5A6 $ % $ maE 5)& CldBal5B66 #o calc%late the Balance $or B we per$orm a !imilar comp%tation5 e/Bal5B6 # ht5c6 $ ht5A6 # ht5c6 $ 5% D maE5ht5a6& ht5b66 6 CldBal5B6 # ht5c6 $ ht5b6 !%btracting the !econd e9%ation $rom the $ir!t yield!5 e/Bal5B6 $ CldBal5B6 # ht5c6 $ ht5c6 D ht5b6 $ 5% D maE5ht5a6& ht5b66 6 canceling and adding 4ldBal)B- to both !ide! gi"e!5 e/Bal5B6 # CldBal5B6 $ % $ 5maE5ht5a6& ht5b66 $ ht5b66 # CldBal5B6 $ % $ 5maE5ht5a6 $ ht5b6& ht5b6 $ ht5b66 B%t ht)a- - ht)b- i! - )ht)b- - ht)a-- D ->ewBal)A- !o ... e/Bal5B6 # CldBal5B6 $ % $ maE5 $e/Bal5A6& )6 E!ing the $act that min):y- D -ma:)-: -y- we get5 e/Bal5B6 # CldBal5B6 $ % D min5 e/Bal5A6& )6 ;o $or a !ingle le$t rotation we ha"e !hown the the new balance! $or the node! A and B are gi"en by the $ollowing e9%ation!5 e/Bal5A6 # CldBal5A6 $ % $ maE5CldBal5B6& )6 e/Bal5B6 # CldBal5B6 $ % D min5e/Bal5A6& )6 >ow let %! loo= at the ca!e o$ a !ingle right rotation. #he ca!e we will %!e i! the !ame one we %!ed $or the !ingle le$t rotation only with all the le$t and right !%btree! !witched aro%nd !o that we ha"e the mirror image o$ the ca!e we %!ed $or o%r le$t rotation. A B / \ / \ / \ / \ B a ##3 c A / \ / \ / \ / \ c b b a <$ we per$orm the !ame calc%lation! that we made $or the le$t rotation we will !ee that the new balance! $or a !ingle right rotation are gi"en by the $ollowing e9%ation!5 e/Bal5A6 # CldBal5A6 D % $ min5CldBal5B6& )6 e/Bal5B6 # CldBal5B6 D % D maE5e/Bal5A6& )6 Fence C(( code $or !ingle le$t and right rotation! wo%ld be5 // Indices into a subtree array enum dir_t { ;'FT # )& GI9HT # % ,- // Geturn the minumum of t/o numbers inline int MI5int a& int b6 { return 5a 2 b6 I a 4 b- , // Geturn the maEimum of t/o numbers inline int MA+5int a& int b6 { return 5a 3 b6 I a 4 b- , // ote that Gotate;eft and GotateGight are <static< member // functions because other/ise they /ould have to re$assign // to the .this. pointer. template 2class 1eyType3 void Avlode21eyType344Gotate;eft5Avlode21eyType3 < 8 root6 { Avlode21eyType3 < oldGoot # root- // perform rotation root # root$3my>ubtree?GI9HTA- oldGoot$3my>ubtree?GI9HTA # root$3my>ubtree?;'FTA- root$3my>ubtree?;'FTA # oldGoot- // update balances oldGoot$3myBal $# 5% D MA+5root$3myBal& )66- root$3myBal $# 5% $ MI5oldGoot$3myBal& )66- , template 2class 1eyType3 void Avlode21eyType344GotateGight5Avlode21eyType3 < 8 root6 { Avlode21eyType3 < oldGoot # root- // perform rotation root # root$3my>ubtree?;'FTA- oldGoot$3my>ubtree?;'FTA # root$3my>ubtree?GI9HTA- root$3my>ubtree?GI9HTA # oldGoot- // update balances oldGoot$3myBal D# 5% $ MI5root$3myBal& )66- root$3myBal D# 5% D MA+5oldGoot$3myBal& )66- , ?e can ma=e thi! code more compact howe"er by %!ing only 4>B rotate method which ta=e! an additional parameter5 the direction in which to rotate. >otice that < ha"e de$ined 'BC# and 0<GF# to be mnemonic con!tant! to inde: into an array o$ !%btree!. < can pa!! the con!tant 'BC# or 0<GF# to the rotation method and it can calc%late the direction oppo!ite the gi"en direction by !%btracting the gi"en direction $rom the n%mber one. <t doe! not matter whether 'BC# i! 6 or 0<GF# i! 6 a! long a! one o$ them i! 6 and the other i! 1. <$ thi! i! the ca!e then5 % $ ;'FT # GI9HT and % $ GI9HT # ;'FT E!ing thi! and the !ame type de$inition! a! be$ore )and the !ame inline $%nction!- the C( ( code $or a !ingle rotation become!5 inline dir_t Cpposite5dir_t dir6 { return dir_t5% $ int5dir66- , // GotateCnce $$ static member function that performs a single // rotation for the given direction. // template 2class 1eyType3 void Avlode21eyType344GotateCnce5Avlode21eyType3 < 8 root& dir_t dir6 { Avlode21eyType3 < oldGoot # root- dir_t other=ir # Cpposite5dir6- // rotate root # tree$3my>ubtree?other=irA- oldGoot$3my>ubtree?other=irA # tree$3my>ubtree?dirA- root$3my>ubtree?dirA # oldGoot- // update balances if 5dir ## ;'FT6 { oldGoot$3myBal $# 5% D MA+5root$3myBal& )66- root$3myBal $# 5% $ MI5oldGoot$3myBal& )66- , else /< dir ## GI9HT </ { oldGoot$3myBal D# 5% $ MI5root$3myBal& )6 6- root$3myBal D# 5% D MA+5oldGoot$3myBal& )66- , //else , ?e can compact thi! code e"en $%rther i$ we play aro%nd with the e9%ation! $or %pdating the balance!. 'et %! %!e the $act that ma:):y- D -min)-:-y-5 for a left rotation oldGoot$3myBal $# 5% D MA+5tree$3myBal& )66- tree$3myBal $# 5% $ MI5oldGoot$3myBal& )66- for a right rotation oldGoot$3myBal D# 5% $ MI5tree$3myBal& )66- tree$3myBal D# 5% D MA+5oldGoot$3myBal& )66- E!ing the abo"e r%le to change all occ%rrence! o$ 3H<>3 to 3HAI3 the!e e9%ation! become5 for a left rotation oldGoot$3myBal $# 5% D MA+5 D5tree$3myBal6& )66- tree$3myBal $# 5% D MA+5 $5oldGoot$3myBal6& )66- for a right rotation oldGoot$3myBal D# 5% D MA+5 $5tree$3myBal6& )66- tree$3myBal D# 5% D MA+5 D5oldGoot$3myBal6& )66- >ote that the di$$erence between %pdating the balance! $or o%r right and le$t rotation! i! only the occ%rrence o$ a J(J where we wo%ld li=e to !ee a J-J in the a!!ignment operator and the !ign o$ the $ir!t arg%ment to the HAI $%nction. <$ we had a $%nction that wo%ld map 'BC# to (1 and 0<GF# to -1 we co%ld m%ltiply by the re!%lt o$ that $%nction to %pdate o%r balance!. ;%ch a $%nction i! f5E6 # % $ @E 3$3 map! 6 to 1 and map! 1 to -1. #hi! $%nction will not map 'BC# and 0<GF# to the !ame "al%e regardle!! o$ which i! 1 and which i! 6 howe"er. <$ we wi!h o%r $%nction to ha"e thi! property then we can m%ltiply )1 - *:- by )0<GF# - 'BC#- !o that the re!%lt 3!witche!3 !ign! accordingly depending %pon whether 'BC# i! 6 or 0<GF# i! 6. #hi! de$ine! a new $%nction 3g35 g5E6 # 5% $ @E65GI9HT $ ;'FT6 <$ 'BC# D 6 and 0<GF# D 1 then5 g5;'FT6 # 5% $ @<)65% $ )6 # %<% # % g5GI9HT6 # 5% $ @<%65% $ )6 # 5$%6<% # $% <$ 'BC# D 1 and 0<GF# D 6 then5 g5;'FT6 # 5% $ @<%65) $ %6 # 5$%6<5$%6 # % g5GI9HT6 # 5% $ @<)65) $ %6 # %<5$%6 # $% ;o a! de!ired the $%nction 3g3 map! 'BC# to (1 and 0<GF# to -1 regardle!! o$ which i! 6 and which i! 1. >ow i$ we introd%ce a new "ariable called 3$actor3 and a!!ign it the "al%e 3g)dir-3 we may %pdate the balance! in o%r rotation method witho%t %!ing a conditional !tatement5 for a rotation in the dir direction oldGoot$3myBal $# factor < 5% D MA+5factor < tree$3myBal& )66- tree$3myBal D# factor < 5% D MA+5factor < oldGoot$3myBal& )66- E!ing thi! the new code $or o%r rotation method become!5 // GotateCnce $$ static member function that performs a single // rotation for the given direction. // Geturn % if the tree height changes due to rotation& // other/ise return ). // template 2class 1eyType3 void Avlode21eyType344GotateCnce5Avlode21eyType3 < 8 root& dir_t dir6 { Avlode21eyType3 < oldGoot # root- dir_t other=ir # Cpposite5dir6- short factor # 5GI9HT $ ;'FT6 < 5% $ 5@ < dir66- // rotate root # tree$3my>ubtree?other=irA- oldGoot$3my>ubtree?other=irA # tree$3my>ubtree?dirA- root$3my>ubtree?dirA # oldGoot- // update balances oldGoot$3myBal $# factor < 5% D MA+5factor < root$3myBal& )66- root$3myBal D# factor < 5% D MA+5factor < oldGoot$3myBal& )66- , Fowe"er altho%gh thi! !econd "er!ion o$ 3rotate3 i! more compact and doe!nJt re9%ire the %!e o$ a conditional te!t on the "ariable 3dir3 <t may act%ally r%n !lower than o%r $ir!t "er!ion o$ 3rotate3 beca%!e the time re9%ired to ma=e the 3te!t3 may well be le!! than the time re9%ired to per$orm the additional m%ltiplication! and !%btraction!. >ow a do%ble rotation can be implemented a! a !erie! o$ !ingle rotation!5 // GotateT/ice $$ static member function to rotate a given node // for the given direction and then the opposite // direction to restore the balance of an A:; tree // Geturn % if the tree height changes due to rotation& // other/ise return ). // template 2class 1eyType3 void Avlode21eyType344GotateT/ice5Avlode21eyType3 < 8 root& dir_t dir6 { dir_t other=ir # Cpposite5dir6- GotateCnce5root$3my>ubtree?other=irA& other=ir6- GotateCnce5root& dir6- , another Method for Calculating Balances After Rotation 4ne may %!e a di$$erent method than the one de!cribed abo"e which i! perhap! !impler. >ote howe"er that the method $or %pdating balance! de!cribed abo"e wor=! regardle!! o$ what n%mber! the balance $actor may contain )a! long a! they are correct -- it wor=! no matter how imbalanced-. <$ we ta=e into acco%nt !ome o$ the condition! that ca%!e a rotation we ha"e more in$ormation to wor= with )li=e that the node to be rotated ha! a balance o$ (* or -* etc..- Cor a !ingle '' rotation we ha"e one o$ two po!!ibilitie!5 A B / \ / \ / \ / \ a B ##3 A c / \ / \ / \ / \ b c a b Balance Factors Before Rotation After Rotation case : A D (* B D (1 A D 6 B D 6 case !: A D (* B D 6 A D (1 B D -1 !o in either ca!e >ewB D 4ldB -1 and newA D -newB !o we get A D - )--B- $or a !ingle le$t rotation. Cor a !ingle 00 rotation the po!!ibilitie! are )#he pict%re i! a mirror image o$ the '' one -- !wap all right and le$t =id! o$ each node- Balance Factors Before Rotation After Rotation case : A D -* B D -1 A D 6 B D 6 case !: A D -* B D 6 A D -1 B D (1 !o in either ca!e >ewB D 4ldB (1 and newA D -newB !o we get A D - )((B- $or a !ingle le$t rotation. #hi! mean! that we can %!e the $ollowing to %pdate balance!5 // 7se mnemonic constants for indicating a change in height enum height_effect_t { H'I9HT_C!HA9' # )& H'I9HT_!HA9' # % ,- // GotateCnce $$ static member function that performs a single // rotation for the given direction. // Geturn % if the tree height changes due to rotation& // other/ise return ). // template 2class 1eyType3 int Avlode21eyType344GotateCnce5Avlode21eyType3 < 8 root& dir_t dir6 { dir_t other=ir # Cpposite5dir6- Avlode21eyType3 < oldGoot # root- // >ee if other=ir subtree is balanced. If it is& then this // rotation /ill <not< change the overall tree height. // Cther/ise& this rotation /ill shorten the tree height. int height!hange # 5root$3my>ubtree?other=irA$3myBal ## )6 I H'I9HT_C!HA9' 4 H'I9HT_!HA9'- // assign ne/ root root # oldGoot$3my>ubtree?other=irA- // ne/$root eEchanges itJs .dir. subtree for itJs parent oldGoot$3my>ubtree?other=irA # root$3my>ubtree?dirA- root$3my>ubtree?dirA # oldGoot- // update balances oldGoot$3myBal # $55dir ## ;'FT6 I $$5root$3myBal6 4 DD5root$3myBal66- return height!hange- , ?e get an e"en nicer !cenario when we loo= at '0 and 0' rotation!. Cor a do%ble '0 rotation we ha"e one o$ three po!!ibilitie!5 A B / \ / \ / \ / \ a ! ##3 A ! / \ / \ / \ / \ / K K \ B c a b% b@ c / \ / \ b% b@ Balance Factors Before Rotation After Rotation case : A D (* B D (1 C D -1 A D -1 B D 6 C D 6 case !: A D (* B D 6 C D -1 A D 6 B D 6 C D 6 case ": A D (* B D -1 C D -1 A D 6 B D 6 C D (1 ;o we get in all three ca!e!5 ne/A # $maE5 oldB& ) 6 ne/! # $min5 oldB& ) 6 ne/B # ) >ow $or a do%ble 0' rotation we ha"e the $ollowing po!!ibilitie! )again the pict%re i! the mirror image o$ the '0 ca!e-5 Balance Factors Before Rotation After Rotation case : A D -* B D (1 C D (1 A D 6 B D 6 C D -1 case !: A D -* B D 6 C D (1 A D 6 B D 6 C D 6 case ": A D -* B D -1 C D (1 A D (1 B D 6 C D 6 ;o we get in all three ca!e!5 ne/A # $min5 oldB& ) 6 ne/! # $maE5 oldB& ) 6 ne/B # ) This is exactly the mirror image of what we had for the LR case: #he node! A and ! in the newly rotated re!%lt !imply exchanged balance factors with one another between the 0' ca!e and the '0 ca!e. ?hat thi! mean! i! that in each ca!e the new balance $actor o$ the new left !%btree i! the !ame and the new balance $actor o$ the new right !%btree i! the !ame5 ne/5left6 # $maE5 oldB& ) 6 ne/5right6 # $min5 oldB& ) 6 ne/5root6 # ) ;o now we can write the code $or a do%ble rotation a! $ollow!5 // GotateT/ice $$ static member function to rotate a given node // t/ice for the given direction in order to // restore the balance of an A:; tree. // Geturn % if the tree height changes due to rotation& // other/ise return ). // template 2class 1eyType3 int Avlode21eyType344GotateT/ice5Avlode21eyType3 < 8 root& dir_t dir6 { dir_t other=ir # Cpposite5dir6- Avlode21eyType3 < oldGoot # root- Avlode21eyType3 < oldCther=ir>ubtree # root$3my>ubtree?other=irA- // assign ne/ root root # oldGoot$3my>ubtree?other=irA$3my>ubtree?dirA- // ne/$root eEchanges itJs .dir. subtree for itJs grandparent oldGoot$3my>ubtree?other=irA # root$3my>ubtree?dirA- root$3my>ubtree?dirA # oldGoot- // ne/$root eEchanges itJs .other$dir. subtree for itJs parent oldCther=ir>ubtree$3my>ubtree?dirA # root$3my>ubtree?other=irA- root$3my>ubtree?other=irA # oldCther=ir>ubtree- // update balances root$3my>ubtree?;'FTA$3myBal # $MA+5root$3myBal& )6- root$3my>ubtree?GI9HTA$3myBal # $MI5root$3myBal& )6- root$3myBal # )- // A double rotation al/ays shortens the overall height of the tree return H'I9HT_!HA9'- , >ow that we ha"e the rotation method! written we K%!t need to worry abo%t when to call them. 4ne help$%l item i! a method called balance56 which i! called when a node get! too hea"y on a partic%lar !ide5 // 7se mnemonic constants for valid balance$factor values enum balance_t { ;'FT_H'A:L # $%& BA;A!'= # )& GI9HT_H'A:L # % ,- // Geturn true if the tree is too heavy on the left side inline static int ;'FT_IMBA;A!'5short bal6 { return 5bal 2 ;'FT_H'A:L6- , // Geturn true if the tree is too heavy on the right side inline static int GI9HT_IMBA;A!'5short bal6 { return 5bal 3 GI9HT_H'A:L6- , // Gebalance $$ static member function to rebalance a 5sub6tree // if it has become imbalanced. // Geturn % if the tree height changes due to rotation& // other/ise return ). template 2class 1eyType3 int Avlode21eyType344GeBalance5Avlode21eyType3 < 8 root6 { int height!hange # H'I9HT_C!HA9'- if 5;'FT_IMBA;A!'5root$3myBal66 { // eed a right rotation if 5root$3my>ubtree?;'FTA$3myBal ## GI9HT_H'A:L6 { // G; rotation needed height!hange # GotateT/ice5root& GI9HT6- , else { // GG rotation needed height!hange # GotateCnce5root& GI9HT6- , , else if 5GI9HT_IMBA;A!'5root$3myBal66 { // eed a left rotation if 5root$3my>ubtree?GI9HTA$3myBal ## ;'FT_H'A:L6 { // ;G rotation needed height!hange # GotateT/ice5root& ;'FT6- , else { // ;; rotation needed height!hange # GotateCnce5root& ;'FT6- , , return height!hange- , #hi! method help! b%t now come! the hard part )in my h%mble opinion- $ig%ring o%t when the height o$ the c%rrent !%btree ha! changed. #etermining $hen the %eight of the Current &u'tree has Changed A$ter we ha"e in!erted or deleted a node $rom the c%rrent !%btree we need to determine i$ the total height o$ the c%rrent tree ha! changed !o that we may pa!! the in$ormation %p the rec%r!ion !tac= to pre"io%! in!tantiation! o$ the in!ertion and deletion method!. 'et %! $ir!t con!ider the ca!e o$ an in!ertion. #he !imple!t ca!e i! at the point where the in!ertion occ%rred. ;ince we ha"e created a node where one did not pre"io%!ly e:i!t we ha"e increa!ed the height o$ the in!erted node $rom 6 to 1. #here$ore we need to pa!! the "al%e 1 )< will %!e 313 $or #0EB and 363 $or CA';B- bac= to the pre"io%! le"el o$ rec%r!ion to indicate the increa!e in the height o$ the c%rrent !%btree. K after insertion K 7;; ################3 K A #he remaining ca!e! $or an in!ertion are almo!t a! !imple. <$ a 6 )CA';B- wa! the 3height-change-indicator3 pa!!ed bac= by in!erting into a !%btree o$ the c%rrent le"el then there i! no height change at the c%rrent le"el. <t i! tr%e that the !tr%ct%re o$ one o$ the !%btree! may ha"e changed d%e to an in!ertion and/or rotation b%t !ince the height o$ the !%btree did not change neither did the height o$ the c%rrent le"el. K after insertion K K ################3 K A A / \ / \ / \ / \ b c b d <$ the c%rrent le"el i! balanced a$ter in!erting the node )b%t be$ore attempting any rotation!- then we K%!t made one !%btree e9%al in height to the other. #here$ore the o"erall height o$ the c%rrent le"el remain! %nchanged and a 6 i! ret%rned. K after insertion K K ################3 K A A / / \ / / \ b b c Be$ore we write the code $or an in!ertion we !till need a method to compare item! while we tra"er!e the tree. >ormally we e:pect thi! !ompare56 method to ret%rn a strcmp56 type re!%lt )@6 DD6 or 86 $or @DD8 re!pecti"ely-. ?e will be a little !nea=y and write o%r own !ompare56 method which will %!e the !ompare56 method o$ the !%pplied 1eyType and ta=e an additional parameter de!cribing whether we want to act%ally compare the "al%e! o$ the two item! or i$ we K%!t want to tra"er!e toward! the ma:imal or minimal element o$ the tree. ?e can %!e the en%meration "al%e! o$ the cmp_t type )'(_!M" MI_!M" MA+_!M"- to indicate the type o$ compari!on that i! de!ired. #hi! e:tra !ompare56 method o$ o%r! doe!nt help m%ch $or in!ertion b%t it will be a big help $or deletion )or !earching- when we need to $ind the minimal or ma:imal element in a !%btree5 // !ompare $$ "erform a comparison of the given 0ey against the given // item using the given criteria 5min& maE& or e*uivalence // comparison6. Geturns4 // '(_!M" if the 0eys are e*uivalent // MI_!M" if this 0ey is less than the itemJs 0ey // MA+_!M" if this 0ey is greater than itemJs 0ey // template 2class 1eyType3 cmp_t Avlode21eyType344!ompare51eyType 0ey& cmp_t cmp6 const { s/itch 5cmp6 { case '(_!M" 4 // >tandard comparison return my=ata$3!ompare50ey6- case MI_!M" 4 // Find the minimal element in this tree return 5my>ubtree?;'FTA ## 7;;6 I '(_!M" 4 MI_!M"- case MA+_!M" 4 // Find the maEimal element in this tree return 5my>ubtree?GI9HTA ## 7;;6 I '(_!M" 4 MA+_!M"- , , ?e are now ready to write the in!ertion method $or o%r A&' tree5 // Insert $$ Insert the given 0ey into the given tree. Geturn the // node if it already eEists. Cther/ise return 7;; to // indicate that the 0ey /as successfully inserted. // 7pon return& the .change. parameter /ill be J%J if // the tree height changed as a result of the insertion // 5other/ise .change. /ill be )6. // template 2class 1eyType3 !omparable21eyType3 < Avlode21eyType344Insert5!omparable21eyType3 < item& Avlode21eyType3 < 8 root& int 8 change6 { // >ee if the tree is empty if 5root ## 7;;6 { // Insert ne/ node here root # ne/ Avlode21eyType35item6- change # H'I9HT_!HA9'- return 7;;- , // Initialize !omparable21eyType3 < found # 7;;- int increase # )- // !ompare items and determine /hich direction to search cmp_t result # root$3!ompare5item$31ey566- dir_t dir # 5result ## MI_!M"6 I ;'FT 4 GI9HT- if 5result M# '(_!M"6 { // Insert into .dir. subtree found # Insert5item& root$3my>ubtree?dirA& change6- if 5found6 return found- // already here $ dont insert increase # result < change- // set balance factor increment , else { // 0ey already in tree at this node increase # H'I9HT_C!HA9'- return root$3my=ata- , root$3myBal D# increase- // update balance factor // $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // re$balance if needed $$ height of current tree increases only if its // subtree height increases and the current tree needs no rotation. // $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ change # 5increase 88 root$3myBal6 I 5% $ GeBalance5root66 4 H'I9HT_C!HA9'- return 7;;- , Leletion i! more complicated than in!ertion. #he height o$ the c%rrent le"el may decrea!e $or two rea!on!5 either a rotation occ%rred to decrea!e the height o$ a !%btree )and hence the c%rrent le"el- or a !%btree !hortened in height re!%lting in a now balanced c%rrent le"el )!%btree wa! 3trimmed down3 to the !ame !i,e a! the other-. M%!t beca%!e a rotation ha! occ%rred howe"er doe! not mean that the !%btree height ha! decrea!ed. #here i! a !pecial ca!e where rotating pre!er"e! the c%rrent !%btree height. ;%ppo!e < ha"e a tree a! $ollow!5 ! / \ A ' / \ = F Leleting 3A3 re!%lt! in the $ollowing )imbalanced- tree5 ! \ ' / \ = F #hi! type o$ imbalance cannot occ%r d%ring in!ertion only d%ring deletion. >otice that the root ha! a balance o$ * b%t it! hea"y !%btree ha! a balance o$ ,ero )the other ca!e wo%ld be a -* and a 6-. Ner$orming a !ingle le$t rotation to re!tore the balance re!%lt! in5 ' / \ ! F \ = #hi! tree ha! the !ame height a! it did be$ore it wa! rotated. Fence we may determine i$ deletion ca%!ed the !%btree height to change by !eeing i$ one o$ the $ollowing occ%rred5 1. <$ the new balance )a$ter deletion- i! ,ero and >4 rotation too= place. *. <$ a rotation too= place b%t wa! not one o$ the !pecial rotation! mentioned abo"e )a -*56 or a *56 rotation-. Cor in!ertion we only needed to chec= i$ a rotation occ%rred to !ee i$ the !%btree height had changed. B%t $or deletion we need to chec= all o$ the abo"e. ;o $or deletion o$ a node we ha"e5 // =elete $$ delete the given 0ey from the given tree. Geturn 7;; // if the 0ey is not found in the tree. Cther/ise return // a pointer to the node that /as removed from the tree. // 7pon return& the .change. parameter /ill be J%J if // the tree height changed as a result of the deletion // 5other/ise .change. /ill be )6. // template 2class 1eyType3 !omparable21eyType3 < Avlode21eyType344=elete51eyType 0ey& Avlode21eyType3 < 8 root& int 8 change& cmp_t cmp6 { // >ee if the tree is empty if 5root ## 7;;6 { // 1ey not found change # H'I9HT_C!HA9'- return 7;;- , // Initialize !omparable21eyType3 < found # 7;;- int decrease # )- // !ompare items and determine /hich direction to search cmp_t result # root$3!ompare50ey& cmp6- dir_t dir # 5result ## MI_!M"6 I ;'FT 4 GI9HT- if 5result M# '(_!M"6 { // =elete from .dir. subtree found # =elete50ey& root$3my>ubtree?dirA& change& cmp6- if 5M found6 return found- // not found $ canJt delete decrease # result < change- // set balance factor decrement , else { // Found 0ey at this node found # root$3my=ata- // set return value // $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // At this point /e 0no/ .result. is zero and .root. points to // the node that /e need to delete. There are three cases4 // // %6 The node is a leaf. Gemove it and return. // // @6 The node is a branch 5has only % child6. Ma0e .root. // 5the pointer to this node6 point to the child. // // N6 The node has t/o children. >/ap items /ith the successor // of .root. 5the smallest item in its right subtree6 and // delete the successor from the right subtree of .root.. // The identifier .decrease. should be reset if the subtree // height decreased due to the deletion of the successor of // .root.. // $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ if 55root$3my>ubtree?;'FTA ## 7;;6 88 5root$3my>ubtree?GI9HTA ## 7;;66 { // Oe have a leaf $$ remove it delete root- root # 7;;- change # H'I9HT_!HA9'- // height changed from % to ) return found- , else if 55root$3my>ubtree?;'FTA ## 7;;6 KK 5root$3my>ubtree?GI9HTA ## 7;;66 { // Oe have one child $$ only child becomes ne/ root Avlode21eyType3 < to=elete # root- root # root$3my>ubtree?5root$3my>ubtree?GI9HTA6 I GI9HT 4 ;'FTA- change # H'I9HT_!HA9'- // Oe Pust shortened the subtree // ull$out the subtree pointers so /e dont recursively delete to=elete$3my>ubtree?;'FTA # to=elete$3my>ubtree?GI9HTA # 7;;- delete to=elete- return found- , else { // Oe have t/o children $$ find successor and replace our // current data item /ith that of the successor root$3my=ata # =elete50ey& root$3my>ubtree?GI9HTA& decrease& MI_!M"6- , , root$3myBal $# decrease- // update balance factor // $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // Gebalance if necessary $$ the height of current tree changes if one // of t/o things happens4 5%6 a rotation /as performed /hich changed // the height of the subtree 5@6 the subtree height decreased and no/ // matches the height of its other subtree 5so the current tree no/ // has a zero balance /hen it previously did not6. // $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ //change # 5decrease6 I 55root$3myBal6 I GeBalance5root6 // 4 H'I9HT_!HA9'6 // 4 H'I9HT_C!HA9' - if 5decrease6 { if 5root$3myBal6 { change # GeBalance5root6- // rebalance and see if height changed , else { change # H'I9HT_!HA9'- // balanced because subtree decreased , , else { change # H'I9HT_C!HA9'- , return found- , Note how in the ca!e o$ both !%btree! o$ the deleted item being non-n%ll < only need one !tatement. #hi! i! d%e to the way Avlode44=elete !et! it! parameter!. #he data pointer pa!!ed on entrance point! to the deleted nodeJ! data on e:it. ;o < K%!t delete the minimal element o$ the right !%btree and !teal it! data a! my-own )ret%rning my $ormer data item on e:it-. And there we ha"e it the maintenance o$ A&' tree manip%lation! the br%nt o$ which i! co"ered in 1 method! none o$ which )e:cept $or delete which i! abo%t 1.1 page!- i! greater than 1 normal page in length incl%ding comment! )and there are a lot-. #he main method! are5 GotateCnce56& GotateT/ice56& GeBalance56& Insert56& =elete56. All other method! are "ery !mall and ea!y to code. #he only method !till mi!!ing i! the >earch56 method and that i! no di$$erent $rom a normal binary tree !earch5 // >earch $$ ;oo0 for the given 0ey using the given comparison criteria& // return 7;; if not found& other/ise return the item address. template 2class 1eyType3 !omparable21eyType3 < Avlode21eyType344>earch51eyType 0ey& Avlode21eyType3 < root& cmp_t cmp6 { cmp_t result- /hile 5root 88 5result # root$3!ompare50ey& cmp666 { root # root$3my>ubtree?5result 2 )6 I ;'FT 4 GI9HTA- , return 5root6 I root$3my=ata 4 7;;- , And let! not $orget the con!tr%ctor and de!tr%ctor5 template 2class 1eyType3 Avlode21eyType344Avlode5!omparable21eyType3 < item6 4 my=ata5item6& myBal5)6 { myBal # ) - my>ubtree?;'FTA # my>ubtree?GI9HTA # 7;; - , template 2class 1eyType3 Avlode21eyType344QAvlode5void6 { if 5my>ubtree?;'FTA6 delete my>ubtree?;'FTA- if 5my>ubtree?GI9HTA6 delete my>ubtree?GI9HTA- , >ow that we ha"e implemented mo!t o$ the method! $or A&' tree manip%lation! we !ho%ld probably $ini!h the declaration that we !tarted near the beginning o$ thi! di!c%!!ion5 Rinclude .!omparable.h. // Indices into a subtree array // CT'4 I /ould place this inside the Avlode class but // /hen I do& gDD complains /hen I use dir_t. 'ven // /hen I prefiE it /ith Avlode44 or Avlode21eyType344 // 5If you can get this /or0ing please let me 0no/6 // enum dir_t { ;'FT # )& GI9HT # % ,- // Avlode $$ !lass to implement an A:; Tree // template 2class 1eyType3 class Avlode { public4 // MaE number of subtrees per node enum { MA+_>7BTG''> # @ ,- static dir_t Cpposite5dir_t dir6 { return dir_t5% $ int5dir66- , // $$$$$ !onstructors and destructors4 Avlode5!omparable21eyType3 < item#7;;6- virtual QAvlode5void6- // $$$$$ (uery attributes4 // 9et this nodeJs data !omparable21eyType3 < =ata56 const { return my=ata- , // 9et this nodeJs 0ey field 1eyType 1ey56 const { return my=ata$31ey56- , // (uery the balance factor& it /ill be a value bet/een $% .. % // /here4 // $% #3 left subtree is taller than right subtree // ) #3 left and right subtree are e*ual in height // % #3 right subtree is taller than left subtree short Bal5void6 const { return myBal- , // 9et the item at the top of the left/right subtree of this // item 5the result may be 7;; if there is no such item6. // Avlode < >ubtree5dir_t dir6 const { return my>ubtree?dirA- , // $$$$$ >earch/Insert/=elete // // CT'4 These are all static functions instead of member functions // because most of them need to modify the given tree root // pointer. If these /ere instance member functions than // that /ould correspond to having to modify the JthisJ // pointer& /hich is not allo/ed in !DD. Most of the // functions that are static and /hich ta0e an A:; tree // pointer as a parameter are static for this reason. // ;oo0 for the given 0ey& return 7;; if not found& // other/ise return the itemJs address. static !omparable21eyType3 < >earch51eyType 0ey& Avlode21eyType3 < root& cmp_t cmp#'(_!M"6 // Insert the given 0ey& return 7;; if it /as inserted& // other/ise return the eEisting item /ith the same 0ey. static !omparable21eyType3 < Insert5!omparable21eyType3 < item& Avlode21eyType3 < 8 root6 { int change- return Insert5item& root& change6- , // =elete the given 0ey from the tree. Geturn the corresponding // node& or return 7;; if it /as not found. static !omparable21eyType3 < =elete51eyType 0ey& Avlode21eyType3 < 8 root& cmp_t cmp#'(_!M"6 { int change- return =elete50ey& root& change& cmp6- , private4 // $$$$$ "rivate data !omparable21eyType3 < my=ata- // =ata field Avlode21eyType3 < my>ubtree?MA+_>7BTG''>A- // >ubtree pointers short myBal- // Balance factor // $$$$$ Goutines that do the <real< insertion/deletion // Insert the given 0ey into the given tree. Geturn the node if // it already eEists. Cther/ise return 7;; to indicate that // the 0ey /as successfully inserted. 7pon return& the .change. // parameter /ill be J%J if the tree height changed as a result // of the insertion 5other/ise .change. /ill be )6. static !omparable21eyType3 < Insert5!omparable21eyType3 < item& Avlode21eyType3 < 8 root& int 8 change6- // =elete the given 0ey from the given tree. Geturn 7;; if the // 0ey is not found in the tree. Cther/ise return a pointer to the // node that /as removed from the tree. 7pon return& the .change. // parameter /ill be J%J if the tree height changed as a result // of the deletion 5other/ise .change. /ill be )6. static !omparable21eyType3 < =elete51eyType 0ey& Avlode21eyType3 < 8 root& int 8 change& cmp_t cmp#'(_!M"6- // Goutines for rebalancing and rotating subtrees // "erform an ++ rotation for the given direction J+J. // Geturn % if the tree height changes due to rotation& // other/ise return ). static int GotateCnce5Avlode21eyType3 < 8 root& dir_t dir6- // "erform an +L rotation for the given direction J+J // Geturn % if the tree height changes due to rotation& // other/ise return ). static int GotateT/ice5Avlode21eyType3 < 8 root& dir_t dir6- // Gebalance a 5sub6tree if it has become imbalanced static int GeBalance5Avlode21eyType3 < 8 root6- // "erform a comparison of the given 0ey against the given // item using the given criteria 5min& maE& or e*uivalence // comparison6. Geturns4 // '(_!M" if the 0eys are e*uivalent // MI_!M" if this 0ey is less than the itemJs 0ey // MA+_!M" if this 0ey is greater than itemJs 0ey cmp_t !ompare51eyType 0ey& cmp_t cmp#'(_!M"6 const- private4 // =isallo/ copying and assignment Avlode5const Avlode21eyType3 86- Avlode 8 operator#5const Avlode21eyType3 86- ,- back to Brad Aleton!s "ome #age