Professional Documents
Culture Documents
Laborator V
Adrian Liţă
2015
1 Scopul laboratorului
Laboratorul V al materiei Structuri de Date şi Algoritmi are ca scop introducerea
structurilor de date arbore binar şi particularizări ale acestuia: arbore binar
de căutare şi arbore AVL.
În acest laborator se parcurg următoarele puncte:
• structura de date a unui arbore binar
2 Desfăşurarea lucrării
În programare, arborii sunt structuri de date utile memorării eficiente a infor-
maţiei, în special pentru a manageria informaţiile memorate. Cele mai frecvente
utilizări ale arborilor sunt:
• managementul memoriei (în alocarea dinamică)
• managementul fişierelor (alocarea în directoare)
• baze de date
1
Un arbore binar reprezintă un arbore ce are doar doi descendenţi: unul în stânga
şi unul în dreapta. Structura unui arbore binar arată în felul următor:
Radacina
Subarbore Subarbore
Stang Drept
1 t y p e d e f s t r u c t node
2 {
3 [ t i p de d a t e i n f o r m a t i e ]
4
5 s t r u c t node ∗ l e f t ;
6 s t r u c t node ∗ r i g h t ;
7 } NODE, ∗PNODE;
Nodul de sus se numeşte rădăcină, iar cei doi descendenţi ai săi se numesc
subarbore stâng şi subarbore drept. Dacă unul din descendenţi nu are niciun
descendent, atunci el se numeşte frunză.
2
1
2 3
NULL NULL
1 t y p e d e f s t r u c t node
2 {
3 int info ;
4 s t r u c t node ∗ l e f t ;
5 s t r u c t node ∗ r i g h t ;
6 } NODE, ∗PNODE;
7
8
9 // f u n c t i a c e c r e e a z a un a r b o r e . p r i m e s t e i n f o r m a t i a pe c a r e o t i n e
r a d a c i n a , s i c e i 2 sub−a r b o r i
10 PNODE makeTree ( i n t i nf o _r a d , PNODE l e f t L e a f , PNODE r i g h t L e a f )
11 {
12 PNODE e = (PNODE) m a l l o c ( s i z e o f (NODE) ) ;
13 i f ( e == NULL)
14 {
15 p r i n t f ( " E r o a r e l a a l o c a r e ! \ n" ) ;
16 exit (0) ; // nu a r e s e n s s a c o n t i n u i
17 }
18 e−>i n f o = i n f o _ r a d ;
3
19 e−> l e f t = l e f t L e a f ;
20 e−>r i g h t = r i g h t L e a f ;
21
22 return e ;
23 }
24
25 i n t main ( )
26 {
27
28 // d e c l a r a m a r b o r i i . f i e c a r e e l e m e n t d i n a r b o r e e s t e un sub−a r b o r e
,
29 // d e c i un a r b o r e l a r a n d u l l u i nu e s t e n e v o i e s a mai i n i t i a l i z a m
cu NULL.
30 // daca va u i t a t i l a f u n c t i a makeTree , a c e a s t a nu s e u i t a l a
pointer efectiv .
31 PNODE rad1 , rad2 , rad3 , rad4 ;
32
33 // i n t a i creem f r u n z e l e
34 rad4 = makeTree ( 4 , NULL, NULL) ;
35 rad2 = makeTree ( 2 , NULL, NULL) ;
36
37 // a p o i s u b a r b o r e l e d r e p t
38 rad3 = makeTree ( 3 , rad4 , NULL) ;
39
40 // s i r a d a c i n a mare
41 rad1 = makeTree ( 1 , rad2 , rad3 ) ;
42
43 system ( " pause " ) ;
44 return 0;
45 }
Acest lucru se face foarte uşor. Arborele binar din figura 1 se reprezintă
prin paranteze astfel: rădăcină(subarbore stâng, subarbore drept). Mai
exact, arborele din figura 2 reprezentat prin paranteze arată în felul următor:
1(2,3(4,N)). Codul care realizează această funcţie este prezentat mai jos:
1 v o i d a f i s a r e _ c u _ p a r a n t e z e (PNODE rad )
2 {
3 i f ( rad == NULL)
4 {
5 p r i n t f ( "N" ) ;
6 return ;
7 }
8
9 p r i n t f ( "%d" , rad−>i n f o ) ;
10
11 i f ( ( rad−> l e f t ) | | ( rad−>r i g h t ) )
4
12 {
13 printf ("(") ;
14 a f i s a r e _ c u _ p a r a n t e z e ( rad−> l e f t ) ;
15 printf (" ,") ;
16 a f i s a r e _ c u _ p a r a n t e z e ( rad−>r i g h t ) ;
17 printf (")") ;
18 }
19 }
• cea mai din dreapta frunză este cel mai mare element al arborelui
• toti subarborii arborelui binar de căutare sunt arbori binari de căutare
• orice operaţie efectuată asupra unui arbore binar de căutare (adăugare,
ştergere noduri) trebuie să-l menţină arbore binar de căutare
5
X
S<X D>X
6
1 t y p e d e f s t r u c t node
2 {
3 int info ;
4 s t r u c t node ∗ l e f t ;
5 s t r u c t node ∗ r i g h t ;
6 } NODE, ∗PNODE;
7
8 PNODE i n s e r a r e (PNODE rad , i n t info_new )
9 {
10 // alocam s p a t i u p e n t r u n o u l nod
11 PNODE e = (PNODE) m a l l o c ( s i z e o f (NODE) ) ;
12 i f ( e == NULL)
13 {
14 p r i n t f ( " E r o a r e l a a l o c a r e ! \ n" ) ;
15 exit (0) ; // nu a r e s e n s s a c o n t i n u i
16 }
17 e−>i n f o = info_new ;
18 e−> l e f t = NULL;
19 e−>r i g h t = NULL;
20
21
22 // v e r i f i c a m s i c a z u l cand a r b o r e l e e s t e g o l
23 i f ( rad == NULL)
24 return e ;
25
26 // s e p a r c u r g e a r b o r e l e pana l a f r u n z a c a r e va d e v e n i r a d a c i n a
27 PNODE f r u n z a = rad ;
28 PNODE i = rad ;
29 while ( i )
30 {
31 frunza = i ;
32 i f ( info_new < i −>i n f o )
33 i = i −> l e f t ;
34 else
35 i = i −>r i g h t ;
36 }
37
38 // i n a c e s t moment p o i n t e r u l f r u n z a a r e a d r e s a n o i i sub−r a d a c i n e
39 i f ( info_new < f r u n z a −>i n f o )
40 f r u n z a −> l e f t = e ;
41 else
42 f r u n z a −>r i g h t = e ;
43
44 r e t u r n rad ;
45 }
46
47 v o i d a f i s a r e _ c u _ p a r a n t e z e (PNODE rad )
48 {
49 ...
50 }
51
52 i n t main ( )
53 {
54 PNODE rad = NULL; // plecam de l a un a r b o r e g o l
55 rad = i n s e r a r e ( rad , 4 ) ;
56 rad = i n s e r a r e ( rad , 5 ) ;
57 rad = i n s e r a r e ( rad , 6 ) ;
7
58 rad = i n s e r a r e ( rad , −4) ;
59 rad = i n s e r a r e ( rad , −5) ;
60 rad = i n s e r a r e ( rad , −6) ;
61 rad = i n s e r a r e ( rad , −1) ;
62 rad = i n s e r a r e ( rad , −2) ;
63 rad = i n s e r a r e ( rad , −3) ;
64 rad = i n s e r a r e ( rad , 1) ;
65 rad = i n s e r a r e ( rad , 2) ;
66 rad = i n s e r a r e ( rad , 3) ;
67
68 a f i s a r e _ c u _ p a r a n t e z e ( rad ) ;
69
70 system ( " pause " ) ;
71 return 0;
72 }
Arborele rezultat în urma rulării codului de mai sus, reprezentat prin paranteze
este: 4(-4(-5(-6,N),-1(-2(-3,N),1(N,2(N,3)))),5(N,6)) şi poate fi vizualizat grafic
în figura 4
-4 5
-5 -1 6
-6 -2 1
-3 2
8
rădăcină. Acest lucru nu va mai fi valabil într-un arbore AVL (capitolul 2.5).
De asemenea, dacă introduceam nodurile în altă ordine, arborele arăta într-o cu
totul altă formă (deşi era tot arbore binar de căutare şi respecta proprietăţile
acestuia).
Arborele AVL reprezintă un caz aparte de arbore binar de căutare, mai exact
este un arbore binar de căutare echilibrat. Acest lucru înseamnă că fiecare
nod trebuie să respecte, pe lângă proprietăţile arborelui binar de căutare şi
următoarea inecuaţie:
|E(x)| < 2 (3)
unde E(x) reprezintă echilibrul nodului x, şi este dat de ecuaţia:
9
13 r e t u r n i n a l t i m e L e f t +1;
14 else
15 r e t u r n i n a l t i m e R i g h t +1;
16 }
Codul aferent calculului echilibrului unui nod (bazat pe ecuaţia 1), precum şi a
calculului echilibrului întregului arbore (bazat pe funcţia de calcul al echilibrului
unui singur nod) este următorul:
1 v o i d c a l c u l _ e c h i l i b r u _ n o d (PNODE x )
2 {
3 x−>b a l a n c e = i n a l t i m e ( x−>r i g h t ) − i n a l t i m e ( x−> l e f t ) ;
4 }
5
6 v o i d c a l c u l _ e c h i l i b r u _ a r b o r e (PNODE rad )
7 {
8 // c a l c u l e a z a e c h i l i b r u l i n t r e g u l u i a r b o r e
9 // ( a d i c a s e t e a z a b a l a n c e p e n t r u f i e c a r e e l e m e n t i n p a r t e )
10 i f ( ! rad )
11 return ;
12
13 c a l c u l _ e c h i l i b r u _ a r b o r e ( rad−>r i g h t ) ;
14 c a l c u l _ e c h i l i b r u _ a r b o r e ( rad−> l e f t ) ;
15
16 c a l c u l _ e c h i l i b r u _ n o d ( rad ) ;
17 }
Un arbore AVL perfect este un arbore AVL în care toate nodurile au echilibrul
0. Un astfel de exemplu este prezentat în figura 5.
4 12
2 6 10 14
1 3 5 7 9 11 13 15
10
nimic că pot gasi un nod într-un timp maxim dat). Pentru a redeveni arbore
AVL, acesta trebuie echilibrat. Operaţiunea de echilibrare se execută pentru
fiecare nod dezechilibrat vizat şi presupune rotiri ale nodurilor.
11
2. se aplică o rotire simplă la stânga asupra rădăcinei
• rotirea dublă la dreapta:
1. se aplică o rotire simplă la stânga descendentului stâng
2. se aplică o rotire simplă la dreapta asupra rădăcinei
12
49 else
50 rad = s R o t i r e D r e a p t a ( rad ) ;
51 }
52 else
53 i f ( rad−>b a l a n c e == 2 )
54 {
55 temp = rad−>r i g h t ;
56 i f ( temp−>b a l a n c e == −1)
57 rad = d R o t i r e S t a n g a ( rad ) ;
58 else
59 rad = s R o t i r e S t a n g a ( rad ) ;
60 }
61 r e t u r n rad ;
62 }
13
3 Probleme
1. Implementaţi o funcţie care creează un arbore binar de căutare dintr-un
vector dat.
14
CS216 Fall 2001
3 3 3 2
2 2 Single 1 3
rotation
1
2
2 2
Single 1 4
3 1 3
1 rotation
3 5
4 4
4 4
2
Single 2 5 2 5
1 4 rotation
1 3 6 1 3 6
3 5
7
6
9/27/01 Page 1 of 4
CS216 Fall 2001
4
4 4
Single
rotation 2 6
2 6 2 6
1 3 5 7
1 3 5 7 1 3 5 7
16 16
15
Step 1: Rotate child and grandchild Step 2: Rotate node and new child (AVL)
4 4
Double 2 6 2 6
rotation
1 3 5 7 1 3 5 15
15 7 16
16
Insert 14 (non-AVL) Step 1: Rotate child and Step 2: Rotate node and
grandchild new child (AVL)
4
4 4
Double
rotation 2 7
2 6 2 6
1 3 6 15
1 3 5 15 1 3 5 7
16
7 16 15 5 14
14 14 16
9/27/01 Page 2 of 4
CS216 Fall 2001
Insert a node
h h +1 h h +2
h h
h h +1 h +1 h
h +2
h +2
Apply a Single Rotation Apply a Double Rotation
9/27/01 Page 3 of 4
CS216 Fall 2001
Single Rotation:
B D
Single
rotation
D B
A
E
h h +1
C E A C
h h +1 h h
h +2
Double Rotation:
B
D
F
B F
A Double
rotation
D
h
G A C E G
h h h h -1 h
C E OR
h-1 h
h h -1 OR
h h
OR
h-1 h
OR
h h
h +1
h +2
9/27/01 Page 4 of 4