You are on page 1of 20

Brad Appleton

Software Tools Developer


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

You might also like