Sunteți pe pagina 1din 299

2

Prefa
Progresele tehnologice n domeniul informaticii au condus la creterea puterii de cal-
cul i a memoriei calculatoarelor electronice, la ieftinirea acestor calculatoare, per-
mind abordarea unor probleme extrem de complexe, din toate sferele activitii
umane. Calculatorul a devenit un instrument indispensabil pentru viaa omului mo-
dern. Penetrarea Internetului i a accesului la resursele informatice mondiale, lrgirea
considerabil a spectrului de aplicaii a contribuit i contribuie la impunerea calcula-
torului ca instrument de lucru vital n activitatea omului. n consecin, cerina de
noi programe n toate domeniile activitii umane a crescut mereu.
De aceea, se impune tot mai pregnant creterea importanei metodologiilor de
realizare a produselor program, necesitatea unei instruiri corespunztoare a noilor
generaii de specialiti i de utilizatori ai calculatoarelor. n formarea specialitilor
n informatic este important dobndirea unor cunotine i deprinderi de a realiza
produse program de o complexitate variat, care s satisfac cerinele beneciarului.
Pentru aceasta este necesar respectarea unei discipline de lucru i cunoaterea unei
metodologii adecvate de proiectare i realizare a acestor produse software. n trecutul
nu prea ndeprtat, n activitatea de instruire a specialitilor n informatic s-a pus
un mai mare accent pe nvarea unor limbaje de programare i pe programarea
propriu-zis, acordndu-se o pondere mai mic analizei i proiectrii programelor.
Specializarea n informatic nu nseamn doar cunoaterea limbajelor de programare,
ci n primul rnd nsuirea metodelor moderne de analiz i proiectare a aplicaiilor
software.
Scopul acestei cri este de a contribui la nvarea programrii ca o disciplin
unitar avnd o fundaie tiinic solid, necesar programatorilor. Pentru aceasta
este nevoie s ncercm s denim mai clar noiunea de programare.
Conform cu [Sed, 1990], programarea poate privit ca o activitate general de
a extinde sau a de a modica funcionalitile unui sistem. Este o activitate general
deoarece ea poate efectuat att de specialiti (programatori) ct i de nespecialiti
(setarea unui telefon celular sau a unei alarme de acces ntr-o ncpere). Din acest
3
4
punct de vedere, activitatea de programare const din dou elemente fundamentale:
o component tehnologic i o component tiinic. Partea tiinic include ele-
mente printre care se regsesc structurile de date i algoritmii necesari descrierii
operaiilor de manipulare a acestor structuri de date. Aceast abordare ne permite o
independena a acestor structuri de date fa de limbajele de programare i fa de
tehnologiile de proiectare utilizate n activitatea de programare.
Programele sunt fcute pentru a rezolva probleme din viaa de zi cu zi. Informaia
prelucrat de un program este stocat cu ajutorul structurilor de date. Aceste
structuri de date grupeaz ntr-o form ecient datele. O structur de date corect
denit poate simplica operaia care prelucreaz acele date sau o poate complica.
De aceea structurile de date au o importan major n activitatea de proiectare
i programare. Programele prelucreaz informaii. Informaiile sunt organizate sub
form de structuri de calcul. Modul n care reprezentm structurile de date afecteaz
claritatea, conciziunea, viteza de rulare i capacitatea de stocare a programului. Dez-
voltarea unui program complex este dicil dac programatorul nu posed cunotine
n domeniul structurilor de date, algoritmicii i a tehnicilor de programare.
Dac nu se cunoate o soluie pentru rezolvarea unei probleme nu exist o soluie
magic de a scrie un program care s rezolve acea problema. Un proverb arm c
dac nu tii cum s ajungi ntr-un anumit loc atunci nu are importan cum ajungi
n acel loc. Mai mult chiar, Murphi arm c orice problem complex are o soluie
simpl eronat. De aceea, nainte de a implementa un program ntr-un anumit limbaj
de programare, este necesar nelegerea problemei, descrierea pas cu pas a soluiei,
cu alte cuvinte este necesar a descrie problema prin intermediul unui algoritm. Din
pcate nu exist un algoritm care s aleag algoritmul care rezolv orice problem.
Ceea ce exist sunt o serie de tehnici de dezvoltare a algoritmilor, numite n general
tehnici de programare.
Scopul principal al lucrrii de fa este familiarizarea celor care doresc s o nvee,
cu activitatea de programare. Vom vedea n ce const aceast activitate i vom
remarca accentul pus pe gndirea omului, pe proiectarea algoritmilor i corectitudinea
lor, calculatorul ind doar unealta care execut ceea ce "dicteaz" programatorul.
Pentru a putea dicta calculatorului avem nevoie de un limbaj neles de ambele pri;
limbajul ales n acest scop este Pascal. De asemenea, vom prezenta metodele de
programare cunoscute n prezent i discutate n literatura de specialitate. Vom nva
s analizm algoritmii, dar vom mai puin preocupai de msurarea complexitii
unui program, accentul ind pus pe modul n care el poate obinut. Noiunile i
conceptele prezentate sunt nsoite de exemple simple, n care s-au folosit: limbajul
Pseudocod n descrierea algoritmilor, un limbaj de specicare informal n descrierea
tipurilor abstracte de date i limbajul Pascal pentru codicare.
Cuprins
1 Bazele algoritmilor 11
1.1 Descrierea algoritmilor . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.1.1 Algoritm, program, programare . . . . . . . . . . . . . . . . . . 11
1.1.2 Scheme logice . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.1.3 Limbajul PSEUDOCOD . . . . . . . . . . . . . . . . . . . . . . 12
1.1.3.1 Algoritmi liniari . . . . . . . . . . . . . . . . . . . . . 15
1.1.3.2 Algoritmi cu ramicaii . . . . . . . . . . . . . . . . . 17
1.1.3.3 Algoritmi ciclici . . . . . . . . . . . . . . . . . . . . . 19
1.1.4 Calculul efectuat de un algoritm . . . . . . . . . . . . . . . . . 22
1.1.5 Ranare n pai succesivi . . . . . . . . . . . . . . . . . . . . . 24
1.1.6 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.1.7 Subalgoritmi . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.1.7.1 Conceptul de subalgoritm . . . . . . . . . . . . . . . . 26
1.1.7.2 Apelul unui subalgoritm . . . . . . . . . . . . . . . . . 29
1.2 Elaborarea algoritmilor. Propoziii nestandard . . . . . . . . . . . . . 31
1.3 Proiectarea ascendent i proiectarea descendent . . . . . . . . . . . . 34
1.4 Proiectarea modular . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.5 Apel recursiv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.6 Programarea structurat . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.7 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2 Complexitatea algoritmilor 51
2.1 Etapele rezolvrii unei probleme . . . . . . . . . . . . . . . . . . . . . 51
2.2 Noiunea de algoritm i cea de program . . . . . . . . . . . . . . . . . 51
2.3 Modelul abstract al Mainii Turing. Teza Turing-Church . . . . . . . . 52
2.4 Analiza, proiectarea i implementarea algoritmilor i complexitatea al-
goritmilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
5
6 CUPRINS
2.5 Operaia de baz, cheia studiului complexitii . . . . . . . . . . . . . 53
2.6 Clase de algoritmi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.7 Eciena algoritmilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.8 Funciile de complexitate . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.9 Apartenena la o clas de complexitate . . . . . . . . . . . . . . . . . . 55
2.10 Limita inferioar sau efortul minimal. Algoritm optimal . . . . . . . . 58
2.11 Complexitatea algoritmilor i dicultatea problemelor . . . . . . . . . 59
2.12 Complexitatea de timp . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.13 Probleme rezonabile i probleme nerezonabile. Clasa problemelor P-
polinomiale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
2.14 Probleme de decizie i probleme de optimizare . . . . . . . . . . . . . . 60
2.15 Clasa problemelor NP (non - deterministic polinomiale) . . . . . . . . 61
2.16 Reducia polinomial a problemelor . . . . . . . . . . . . . . . . . . . 61
2.17 Teorema lui Cook. Probleme NP-Complete . . . . . . . . . . . . . . . 62
2.18 Clasa problemelor NP-Complete . . . . . . . . . . . . . . . . . . . . . 62
2.19 Marea ntrebare a Complexitii algoritmilor . . . . . . . . . . . . . . 63
2.20 Algoritmi aproximativi . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
2.21 Probleme insolvabile algoritmic . . . . . . . . . . . . . . . . . . . . . . 65
2.22 Complexitatea algoritmilor, calculatorul i viitorul . . . . . . . . . . . 66
3 Pogramare n limbajul PASCAL 67
3.1 Mediul de programare Turbo Pascal . . . . . . . . . . . . . . . . . . . 67
3.2 Programe simple Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.3 Structura unui program Pascal . . . . . . . . . . . . . . . . . . . . . . 73
3.4 Constante i variabile Pascal . . . . . . . . . . . . . . . . . . . . . . . 74
3.5 Tipuri de date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
3.5.1 Tipul ntreg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
3.5.2 Tipul real . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
3.5.3 Tipul boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.5.4 Tipul caracter . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.5.5 Tipul enumerare . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.5.6 Tipul subdomeniu . . . . . . . . . . . . . . . . . . . . . . . . . 79
3.6 Expresii Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
3.6.1 Funcii predenite . . . . . . . . . . . . . . . . . . . . . . . . . 79
3.6.2 Expresii aritmetice . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.6.3 Expresii relaionale . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.6.4 Expresii logice . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.7 Declaraii Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
CUPRINS 7
3.8 Denirea constantelor . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.9 Denirea tipurilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.10 Declararea variabilelor . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
3.11 Instruciuni Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
3.11.1 Instruciunea de atribuire . . . . . . . . . . . . . . . . . . . . . 86
3.11.2 Instruciunea compus i instruciunea vid . . . . . . . . . . . 87
3.11.3 Citirea i scrierea datelor . . . . . . . . . . . . . . . . . . . . . 87
3.11.4 Instruciuni condiionale . . . . . . . . . . . . . . . . . . . . . . 89
3.11.5 Instruciuni repetitive . . . . . . . . . . . . . . . . . . . . . . . 91
3.12 Subprograme Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
3.13 Funcii Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
3.14 Instruciunea apel de procedur . . . . . . . . . . . . . . . . . . . . . . 99
3.15 Apel recursiv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
3.16 Tipuri de date structurate . . . . . . . . . . . . . . . . . . . . . . . . . 106
3.17 Tipul referin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
3.18 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
4 Structuri de date 121
4.1 Lista liniar simplu nlnuit . . . . . . . . . . . . . . . . . . . . . . 121
4.1.1 Deniii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
4.1.2 Operaii specice listei . . . . . . . . . . . . . . . . . . . . . . . 123
4.1.3 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . 128
4.2 Lista dublu nlnuit . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
4.2.1 Deniii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
4.2.2 Operaii specice listei . . . . . . . . . . . . . . . . . . . . . . . 131
4.2.3 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . 138
4.3 Stiva (stack) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
4.3.1 Generaliti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
4.3.2 Stiva alocare static . . . . . . . . . . . . . . . . . . . . . . . 140
4.3.3 Stiva alocare dinamic . . . . . . . . . . . . . . . . . . . . . . 141
4.3.4 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . 143
4.4 Coada (queue) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
4.4.1 Generaliti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
4.4.2 Coada alocare static . . . . . . . . . . . . . . . . . . . . . . 144
4.4.3 Coada alocare dinamic . . . . . . . . . . . . . . . . . . . . . 146
4.4.4 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . 147
4.5 Arborele binar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
4.5.1 Deniii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
8 CUPRINS
4.5.2 Operaii ntr-un arbore binar AB . . . . . . . . . . . . . . . . . 150
4.5.3 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . 153
4.6 Grafuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
4.6.1 Grafuri orientate . . . . . . . . . . . . . . . . . . . . . . . . . . 153
4.6.1.1 Deniii i generaliti . . . . . . . . . . . . . . . . . . 153
4.6.1.2 Reprezentarea grafurilor orientate . . . . . . . . . . . 155
4.6.2 Grafuri neorientate . . . . . . . . . . . . . . . . . . . . . . . . . 157
4.6.2.1 Deniii i generaliti . . . . . . . . . . . . . . . . . . 157
4.6.2.2 Reprezentarea grafurilor neorientate . . . . . . . . . . 158
4.6.3 Grafuri planare . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
5 Tehnici de cutare 161
5.1 Introducere n tehnicile de cutare . . . . . . . . . . . . . . . . . . . . 161
5.1.1 Cutare secvenial . . . . . . . . . . . . . . . . . . . . . . . . 162
5.1.1.1 Descrierea general a metodei . . . . . . . . . . . . . 162
5.1.1.2 Probleme rezolvate pentru cutare secvenial . . . . 165
5.1.1.3 Probleme propuse . . . . . . . . . . . . . . . . . . . . 169
5.1.2 Cutare binar . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
5.1.2.1 Descrierea general a metodei . . . . . . . . . . . . . 171
5.1.2.2 Descrierea algoritmului de cutare n Pseudocod . . . 172
5.1.2.3 Performana algoritmului de cutare . . . . . . . . . . 174
5.1.2.4 Probleme rezolvate pentru cutarea binar . . . . . . 175
5.1.2.5 Probleme propuse . . . . . . . . . . . . . . . . . . . . 181
5.2 Arbori de cutare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
5.2.1 Arbore binar de cutare ABC . . . . . . . . . . . . . . . . . . . 181
5.2.1.1 Descrierea general a arborelui binar de cutare . . . 181
5.2.1.2 Implementarea unui nod al arborelui ABC . . . . . . 183
5.2.1.3 Operaii ntr-un ABC . . . . . . . . . . . . . . . . . . 183
5.2.1.4 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . 189
5.2.2 Arbore binar de cutare balansat n nlime . . . . . . . . . . 192
5.2.2.1 Descrierea general a arborelui balansat n nlime . 192
5.2.2.2 Implementarea unui nod al arborelui ABCBI . . . . . 194
5.2.2.3 Operaii ntr-un ABCBI . . . . . . . . . . . . . . . . 195
5.2.2.4 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . 200
5.2.2.5 Performanele algoritmilor n ABCBI . . . . . . . . . 206
5.2.3 Arbore binar de cutare balansat n greutate ABCBG . . . . . 206
5.2.3.1 Descrierea general a arborelui balansat n greutate . 206
5.2.3.2 Implementarea unui nod al arborelui ABCBG . . . . 209
CUPRINS 9
5.2.3.3 Operaii ntr-un ABCBG . . . . . . . . . . . . . . . . 209
5.2.3.4 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . 213
5.2.4 Arbore de cutare 2-3 AC2-3 . . . . . . . . . . . . . . . . . . . 221
5.2.4.1 Descrierea general a arborelui de cutare 2-3 . . . . 221
5.2.4.2 Implementarea nodurilor AC2-3 . . . . . . . . . . . . 222
5.2.4.3 Operaii ntr-un AC2-3 . . . . . . . . . . . . . . . . . 223
5.2.4.4 Performanele algoritmilor n AC2-3 . . . . . . . . . . 231
5.3 Funcii de cutare hash . . . . . . . . . . . . . . . . . . . . . . . . . . 241
5.3.1 Introducere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
5.3.2 Funcii hash . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
5.3.2.1 Funcia hash - metoda mpririi . . . . . . . . . . . . 243
5.3.2.2 Funcia hash - metoda ptratului mediu . . . . . . . . 244
5.3.2.3 Funcia hash - metoda ndoirii . . . . . . . . . . . . . 244
5.3.2.4 Funcia hash - metoda cifrelor . . . . . . . . . . . . . 245
5.3.2.5 Funcia hash - metoda dependent de lungimea cheii 245
5.3.2.6 Funcia hash metoda codicrii algebrice . . . . . . 245
5.3.2.7 Funcii hash - metoda multiplicativ . . . . . . . . . . 246
5.3.3 Performana funciilor hash . . . . . . . . . . . . . . . . . . . . 246
5.3.4 Tehnici de rezoluiune a coliziunilor . . . . . . . . . . . . . . . 246
5.3.4.1 Introducere . . . . . . . . . . . . . . . . . . . . . . . . 246
5.3.4.2 Tehnici de rezoluiune a coliziunilor prin adresare de-
schis . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
5.3.4.3 Tehnici de rezoluiune a coliziunilor prin adresare n-
lnuit . . . . . . . . . . . . . . . . . . . . . . . . . . 256
6 Tehnici de sortare 259
6.1 Istoric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
6.2 Algoritmi de sortare . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
6.2.1 Algoritmul de sortare prin metoda bulelor (bubble sort) . . . . 264
6.2.1.1 Descrierea general a metodei . . . . . . . . . . . . . 264
6.2.1.2 Descrierea algoritmului . . . . . . . . . . . . . . . . . 264
6.2.1.3 Implementarea algoritmului . . . . . . . . . . . . . . . 266
6.2.1.4 Complexitatea algoritmului . . . . . . . . . . . . . . . 267
6.2.2 Algoritmul de sortare prin selecie . . . . . . . . . . . . . . . . 267
6.2.2.1 Descrierea general a metodei . . . . . . . . . . . . . 267
6.2.2.2 Descrierea algoritmului . . . . . . . . . . . . . . . . . 267
6.2.2.3 Implementarea algoritmului . . . . . . . . . . . . . . . 269
6.2.2.4 Complexitatea algoritmului . . . . . . . . . . . . . . . 270
10 CUPRINS
6.2.3 Algoritmul de sortare prin inserare . . . . . . . . . . . . . . . . 270
6.2.3.1 Descrierea general a metodei . . . . . . . . . . . . . 270
6.2.3.2 Descrierea algoritmului . . . . . . . . . . . . . . . . . 271
6.2.3.3 Implementarea algoritmului . . . . . . . . . . . . . . . 272
6.2.3.4 Complexitatea algoritmului . . . . . . . . . . . . . . . 273
6.2.4 Algoritmul de sortare Shell . . . . . . . . . . . . . . . . . . . . 274
6.2.4.1 Descrierea general a metodei . . . . . . . . . . . . . 274
6.2.4.2 Descrierea algoritmului . . . . . . . . . . . . . . . . . 275
6.2.4.3 Implementarea algoritmului . . . . . . . . . . . . . . . 276
6.2.4.4 Complexitatea algoritmului . . . . . . . . . . . . . . . 278
6.2.5 Algoritmul de sortare rapid (quicksort) . . . . . . . . . . . . . 278
6.2.5.1 Descrierea general a metodei . . . . . . . . . . . . . 278
6.2.5.2 Descrierea algoritmului . . . . . . . . . . . . . . . . . 278
6.2.5.3 Implementarea algoritmului . . . . . . . . . . . . . . . 280
6.2.5.4 Complexitatea algoritmului . . . . . . . . . . . . . . . 281
6.2.6 Algoritmul de sortare prin interclasare (mergesort) . . . . . . . 282
6.2.6.1 Descrierea general a metodei . . . . . . . . . . . . . 282
6.2.6.2 Descrierea algoritmului . . . . . . . . . . . . . . . . . 282
6.2.6.3 Implementarea algoritmului . . . . . . . . . . . . . . . 283
6.2.6.4 Complexitatea algoritmului . . . . . . . . . . . . . . 286
6.2.7 Algoritmul de sortare prin ansambluri (heapsort) . . . . . . . . 287
6.2.7.1 Descrierea general a metodei . . . . . . . . . . . . . 287
6.2.7.2 Descrierea algoritmului . . . . . . . . . . . . . . . . . 287
6.2.7.3 Implementarea algoritmului . . . . . . . . . . . . . . . 291
6.2.7.4 Complexitatea algoritmului . . . . . . . . . . . . . . . 292
6.2.8 Algoritmul de sortare RADIX . . . . . . . . . . . . . . . . . . . 293
6.2.8.1 Descrierea general a metodei . . . . . . . . . . . . . 293
6.2.8.2 Descrierea algoritmului . . . . . . . . . . . . . . . . . 293
6.2.8.3 Implementarea algoritmului . . . . . . . . . . . . . . . 294
6.2.8.4 Complexitatea algoritmului . . . . . . . . . . . . . . . 296
Bibliograe 297
Capitolul 1
Bazele algoritmilor
1.1 Descrierea algoritmilor
1.1.1 Algoritm, program, programare
Ce este un algoritm? O deniie matematic, riguroas, este greu de dat, chiar
imposibil fr a introduce i alte noiuni [Giu, 2004]. Vom ncerca n continuare o
descriere a ceea ce se nelege prin algoritm.
Vom constata c un algoritm este un text nit, o secven nit de propoziii ale
unui limbaj. Din cauz c este inventat special n acest scop, un astfel de limbaj este
numit limbaj de descriere a algoritmilor. Fiecare propoziie a limbajului precizeaz o
anumit regul de calcul, aa cum se va observa atunci cnd vom prezenta limbajul
Pseudocod.
Algoritmii au urmtoarele caracteristici: generalitate, nitudine i unicitate [Liv,
1980].
n descrierea algoritmilor se folosesc mai multe limbaje de descriere, dintre care
cele mai des folosite sunt:
- limbajul schemelor logice;
- limbajul Pseudocod.
1.1.2 Scheme logice
Schema logic este un mijloc de descriere a algoritmilor prin reprezentare grac. Re-
gulile de calcul ale algoritmului sunt descrise prin blocuri (guri geometrice) reprezen-
tnd operaiile (paii) algoritmului, iar ordinea lor de aplicare (succesiunea operaiilor)
11
12 1. Bazele algoritmilor
este indicat prin sgei. Fiecrui tip de operaie i este consacrat o gur geome-
tric (un bloc tip) n interiorul creia se va nscrie operaia din pasul respectiv [Liv,
1980].
Prin execuia unui algoritm descris printr-o schem logic se nelege efectuarea tu-
turor operaiilor precizate prin blocurile schemei logice, n ordinea indicat de sgei.
n descrierea unui algoritm, deci i ntr-o schem logic, intervin variabile care
marcheaz att datele cunoscute iniial, ct i rezultatele dorite, precum i alte rezul-
tate intermediare necesare n rezolvarea problemei. Deoarece variabila joac un rol
central n programare este bine s denim acest concept.
Variabila denete o mrime care i poate schimba valoarea n timp. Ea are un
nume i o valoare. Este posibil ca variabila nc s nu aib asignat o valoare, situaie
n care vom spune c ea este neiniializat.
Valorile pe care le poate lua variabila aparin unei mulimi D pe care o vom numi
domeniul variabilei. Variabila este folosit cu un anumit scop, ea noteaz o anumit
mrime, cu o anumit semnicaie. n concluzie o variabil este cunoscut prin (nume,
domeniul D, valoare, semnicaie), unde valoarea aparine mulimii D.
Pentru claritatea textului unui algoritm este important s se cunoasc semnicaia
ecrei variabile, s e menionat expres aceast semnicaie. n nici un caz nu se
recomand s se foloseasc acelai nume pentru variabile cu semnicaii diferite, caz
care provoc confuzii i chiar erori grave. Vom enuna acestea sub forma unor reguli
cu care e bine s ne obinuim i s le respectm n activitatea de programare.
1.1.3 Limbajul PSEUDOCOD
Limbajul Pseudocod este un limbaj folosit n scopul proiectrii algoritmilor i este
format din propoziii asemntoare propoziiilor limbii romne, care corespund struc-
turilor de calcul folosite n construirea algoritmilor. Acesta va limbajul folosit de
noi n proiectarea algoritmilor i va denit n cele ce urmeaz.
innd seama c realizarea unui algoritm pentru rezolvarea unei probleme nu
este ntotdeauna o sarcin simpl, c n acest scop sunt folosite anumite metode pe
care le vom descrie n capitolele urmtoare, n etapele intermediare pentru obinerea
algoritmului vom folosi propoziii curente din limba romn [Fre, 1986].
Acestea sunt considerate elemente nenisate din algoritm, asupra crora trebuie
s se revin i le vom numi propoziii nestandard. Deci limbajul Pseudocod are dou
tipuri de propoziii: propoziii standard, care vor prezentate ecare cu sintaxa i
semnicaia (semantica) ei i propoziii nestandard. Aa cum se va arta mai trziu,
propoziiile nestandard sunt texte care descriu pri ale algoritmului nc incomplet
elaborate, nenisate, asupra crora urmeaz s se revin. Ele se recunosc prin faptul
1.1. Descrierea algoritmilor 13
c ncep ntotdeauna cu semnul @ i se termin cu caracterul ;.
Pe lng aceste propoziii standard i nestandard, n textul algoritmului vom mai
introduce propoziii explicative, numite comentarii. Pentru a le distinge de celelalte
propoziii, comentariile vor nchise ntre acolade. Rolul lor va explicat puin mai
trziu.
Prin execuia unui algoritm descris n Pseudocod se nelege efectuarea operaiilor
precizate de propoziiile algoritmului, n ordinea citirii lor (de sus n jos i de la stnga
spre dreapta).
Propoziiile standard ale limbajului Pseudocod folosite n aceast lucrare, core-
spund structurilor de calcul prezentate n Figura 1.1 i vor prezentate n continuare.
Da
Nu
cond
A
A
Nu Da
A
cond
B
B
(a) structura
secvenial
(b) structura
alternativ
(c) structura
repetitiv
Figura 1.1: Structuri elementare de calcul
n Figura 1.1, prin A, B s-au notat subscheme logice, adic secvene de oricte
structuri construite conform celor trei reguli menionate n continuare.
Structura secvenial (Figura 1.1 a) este redat prin concatenarea propoziiilor,
simple sau compuse, ale limbajului Pseudocod, care vor executate n ordinea ntl-
nirii lor n text.
Propoziiile simple din limbajul Pseudocod sunt CITETE, TIPARETE, FIE
i apelul de subprogram. Propoziiile compuse corespund structurilor alternative i
repetitive.
Structura alternativ din Figura 1.1 b este redat n Pseudocod prin propoziia
DAC, prezentat n seciunea 1.1.3.2, iar structura repetitiv din Figura 1.1 c este
redat n Pseudocod prin propoziia CTTIMP, prezentat n seciunea 1.1.3.3.
Bohm i Jacopini [Bh, 1966] au demonstrat c orice algoritm poate descris
folosind numai aceste trei structuri de calcul.
14 1. Bazele algoritmilor
Propoziiile DATE i REZULTATE sunt folosite n faza de specicare a prob-
lemelor, adic enunarea riguroas a acestora.
Fiecare propoziie standard ncepe cu un cuvnt cheie, aa cum se va vedea n
cele ce urmeaz. Pentru a deosebi aceste cuvinte de celelalte denumiri, construite de
programator, n acest capitol vom scrie cuvintele cheie cu litere mari. Menionm c
propoziiile simple se termin cu caracterul ; n timp ce propoziiile compuse, deci
cele n interiorul crora se a alte propoziii, au un marcaj de sfrit propriu. De
asemenea, menionm c propoziiile limbajului Pseudocod vor luate n seam n
ordinea ntlnirii lor n text, asemenea oricrui text al limbii romne.
Propoziia DATE se folosete pentru precizarea datelor iniiale, deci a datelor
considerate cunoscute n problem (numite i date de intrare) i are sintaxa:
DATE list ;
unde list conine toate numele variabilelor a cror valoare iniial este cunoscut.
n general, prin list se nelege o succesiune de elemente de acelai fel desprite
prin virgul. Deci n propoziia DATE, n dreapta acestui cuvnt se vor scrie acele
variabile care marcheaz mrimile cunoscute n problem.
Pentru precizarea rezultatelor dorite se folosete propoziia standard:
REZULTATE list;
n construcia "list" ce urmeaz dup cuvntul REZULTATE ind trecute numele
variabilelor care marcheaz (conin) rezultatele cerute n problem.
Acum putem preciza mai exact ce nelegem prin cunoaterea complet a problemei
de rezolvat. Evident, o problem este cunoscut atunci cnd se tie care sunt datele
de intrare ce denesc problema dat i rezultatele ce trebuiesc obinute.
Deci, pentru cunoaterea unei probleme este necesar precizarea variabilelor care
marcheaz datele considerate cunoscute n problem, care va reectat printr-o
propoziie DATE i cunoaterea exact a rezultatelor problemei, care se va reecta
prin propoziia REZULTATE.
Variabilele prezente n aceste propoziii au anumite semnicaii, presupuse cunos-
cute. Cunoaterea acestora, scrierea lor explicit, formeaz ceea ce vom numi n
continuare specicarea problemei. Specicarea unei probleme este o activitate foarte
important dar nu i simpl.
De exemplu, pentru rezolvarea ecuaiei de gradul al doilea, specicarea problemei,
poate :
DATE a,b,c; { Coecienii ecuaiei }
REZULTATE x1,x2; { Rdcinile ecuaiei }
1.1. Descrierea algoritmilor 15
Aceast specicaie este ns incomplet. Nu ntotdeauna ecuaia are rdcini
reale. n cazul n care rdcinile sunt complexe putem nota prin x1, x2 partea re-
al, respectiv partea imaginar a rdcinilor. Sau, pur i simplu, nu ne intereseaz
valoarea rdcinilor n acest caz, ci doar faptul c ecuaia nu are rdcini reale.
Cu alte cuvinte avem nevoie de un mesaj care s ne indice aceast situaie (vezi
exemplul 1.1.2), sau de un indicator, e el numit ind. Acest indicator va lua valoarea
1 dac rdcinile sunt reale i valoarea 0 n caz contrar. Deci specicaia mai complet
a problemei este:
DATE a,b,c; { Coecienii ecuaiei }
REZULTATE ind, {ind=1 pt. rdcini reale, 0 pt complexe}
x1,x2; {Rdcinile ecuaiei, n cazul ind=1, respectiv}
{partea real i cea imaginar n cazul ind=0}
Evident c specicarea problemei este o etap important pentru gsirea unei
metode de rezolvare i apoi n proiectarea algoritmului corespunztor. Nu se poate
rezolva o problem dac aceasta nu este bine cunoscut, adic nu avem scris speci-
carea problemei.
"Cunoate complet problema" este prima regul ce trebuie respectat pentru a
obine ct mai repede un algoritm corect pentru rezolvarea ei.
1.1.3.1 Algoritmi liniari
Propoziiile CITETE i TIPRETE sunt folosite pentru iniializarea variabilelor
de intrare cu datele cunoscute n problem, respectiv pentru tiprirea (aarea) rezul-
tatelor obinute. n etapa de programare propriu-zis acestor propoziii le corespund,
ntr-un limbaj de programare, instruciuni de intrare-ieire.
Propoziia CITETE se folosete pentru precizarea datelor iniiale, deci a datelor
considerate cunoscute n problem (numite i date de intrare) i are sintaxa:
CITETE list ;
unde list conine toate numele variabilelor a cror valoare iniial este cunoscut.
Deci n propoziia CITETE, n dreapta acestui cuvnt se vor scrie acele variabile
care apar n propoziia DATE n specicarea problemei. Se subnelege c aceste
variabile sunt iniializate cu valorile cunoscute corespunztoare.
Pentru aarea rezultatelor dorite, pe care calculatorul o va face prin tiprirea lor
pe hrtie sau aarea pe ecran, se folosete propoziia standard:
TIPRETE list ;
16 1. Bazele algoritmilor
n construcia list ce urmeaz dup cuvntul TIPRETE ind trecute numele vari-
abilelor a cror valori dorim s le am. Ele sunt de obicei rezultatele cerute n
problem, specicate i n propoziia REZULTATE.
Blocului de atribuire dintr-o schem logic i corespunde n Pseudocod propoziia
standard:
[FIE] var := expresie ;
Aceast propoziie este folosit pentru a indica un calcul algebric, al expresiei
care urmeaz dup simbolul de atribuire ":=" i de atribuire a rezultatului obinut
variabilei var. Expresia din dreapta semnului de atribuire poate orice expresie
algebric simpl, cunoscut din manualele de matematic din liceu i construit cu
cele patru operaii: adunare, scdere, nmulire i mprire (notate prin caracterele
+, -, *, respectiv /).
Prin scrierea cuvntului FIE ntre paranteze drepte se indic posibilitatea omiterii
acestui cuvnt din propoziie. El s-a folosit cu gndul ca ecare propoziie s nceap
cu un cuvnt al limbii romne care s reprezinte numele propoziiei. De cele mai multe
ori vom omite acest cuvnt. Atunci cnd vom scrie succesiv mai multe propoziii de
atribuire vom folosi cuvntul FIE numai n prima propoziie, omindu-l n celelalte.
Din cele de mai sus rezult c o variabil poate iniializat att prin atribuire
(deci dac este variabila din stnga semnului de atribuire :=) ct i prin citire (cnd
face parte din lista propoziiei CITETE). O greeal frecvent, pe care o fac n-
ceptorii este folosirea variabilelor neiniializate. Evident, c o expresie n care apar
variabile care nu au valori nu poate calculat, ea nu este denit. Deci nu se folosesc
variabile neiniializate.
Pentru a marca nceputul descrierii unui algoritm vom folosi propoziia:
ALGORITMUL nume ESTE:
De asemenea, prin propoziia:
SFALGORITM
vom marca sfritul unui algoritm.
Algoritmii care pot descrii folosind numai propoziiile prezentate mai sus se
numesc algoritmi liniari.
Ca exemplu de algoritm liniar prezentm un algoritm ce determin viteza V cu
care a mers un autovehicul ce a parcurs distana D n timpul T.
1.1. Descrierea algoritmilor 17
Exemplul 1.1.1.
ALGORITMUL Viteza ESTE: { Calculeaz viteza }
{ D = Distana (spaiul) }
{ T = Timpul; V = Viteza }
CITETE D,T; { V:= spaiu/timp }
FIE V:=D/T;
TIPRETE V;
SFALGORITM
1.1.3.2 Algoritmi cu ramicaii
Foarte muli algoritmi execut anumite calcule n funcie de satisfacerea unor condiii.
Aceste calcule sunt redate de structura alternativ prezentat n Figura 1.1 b, creia
i corespunde propoziia Pseudocod:
DAC cond
ATUNCI A
ALTFEL B
SFDAC
sau varianta redus a ei:
DAC cond
ATUNCI A
SFDAC
folosit n cazul n care grupul de propoziii B este vid.
Aceste propoziii redau n Pseudocod structura alternativ de calcul. n primul
rnd, este necesar vericarea condiiei scrise dup cuvntul DAC. n cazul c
aceast condiie este adevrat se va executa grupul de propoziii A. n cazul n care
aceast condiie este fals se va executa grupul de propoziii B, dac este prezent
ramura ALTFEL. Indiferent care dintre secvenele A sau B a fost executat, se va
continua cu propoziia urmtoare propoziiei DAC, ce urmeaz dup marcatorul de
sfrit SFDAC.
O generalizare a structurii alternative realizat de propoziia DAC este structura
selectiv:
SELECTEAZ i DINTRE
v1: A1;
v2: A2;
. . .
vn: An
SFSELECTEAZ
18 1. Bazele algoritmilor
structur echivalent cu urmtorul text Pseudocod:
DAC i=v1
ATUNCI A1
ALTFEL
DAC i=v2
ATUNCI A2
ALTFEL
. . .
DAC i=vn
ATUNCI An
SFDAC
...
SFDAC
SFDAC
Cu propoziiile prezentate pn acum putem descrie un numr nsemnat de algo-
ritmi. Acetia se numesc algoritmi cu ramicaii.
De exemplu, vom descrie un algoritm pentru rezolvarea ecuaiei de gradul al doilea.
Am prezentat n 1.1.3 aceast problem i am precizat semnicaia variabilelor res-
pective. Pe lng aceste variabile, pentru rezolvarea problemei mai avem nevoie de
dou variabile auxiliare:
delta - pentru discriminantul ecuaiei;
r - pentru valoarea radicalului folosit n calculul rdcinilor.
Exemplul 1.1.2.
ALGORITMUL EcGrDoi ESTE: { Rezolvarea }
{ ecuaiei de gradul doi }
CITETE a,b,c; { a,b,c = coecienii ecuaiei }
FIE delta:=b*b-4*a*c;
DAC delta<0
ATUNCI ind:=0; {Cazul rdcini complexe }
@r:=radical din (-delta);
x1:=-b/(a+a);
x2:=r/(a+a);
ALTFEL ind:=1; {cazul rdcini reale }
@r:=radical din delta;
x1:=(-b-r)/(a+a);
x2:=(-b+r)/(a+a);
SFDAC
1.1. Descrierea algoritmilor 19
TIPRETE ind, x1,x2;
SFALGORITM
1.1.3.3 Algoritmi ciclici
n rezolvarea multor probleme trebuie s efectum aceleai calcule de mai multe ori,
sau s repetm calcule asemntoare. De exemplu, pentru a calcula suma a dou
matrice va trebui s adunm un element al primei matrice cu elementul de pe aceeai
poziie din a doua matrice, aceast adunare repetndu-se pentru ecare poziie n
parte. Alte calcule trebuiesc repetate n funcie de satisfacerea unor condiii.
n acest scop n limbajul Pseudocod exist trei propoziii standard: CTTIMP,
REPET i PENTRU. Propoziia CTTIMP are sintaxa:
CTTIMP cond EXECUT A SFCT
i cere execuia repetat a grupului de propoziii A, n funcie de condiia "cond". Mai
exact, se evalueaz condiia "cond"; dac aceasta este adevrat se execut grupul A
i se revine la evaluarea condiiei. Dac ea este fals execuia propoziiei se termin
i se continu cu propoziia care urmeaz dup SFCT.
Dac de prima dat condiia este fals grupul A nu se va executa niciodat, altfel
se va repeta execuia grupului de propoziii A pn cnd condiia va deveni fals. Din
cauz c nainte de execuia grupului A are loc vericarea condiiei, aceast structur
se mai numete structur repetitiv condiionat anterior. Ea reprezint structura
repetitiv prezentat n Figura 1.1 c.
Ca exemplu de algoritm n care se folosete aceast structur ciclic s rezolvm
algoritmul lui Euclid pentru calculul celui mai mare divizor comun a dou numere.
Exemplul 1.1.3.
ALGORITMUL Euclid ESTE: { Cel mai mare divizor comun}
CITETE n1,n2; {Cele dou numere a cror divizor se cere}
FIE d:=n1; i:=n2;
CTTIMP i0 EXECUT
r:=d modulo i; d:=i; i:=r
SFCT
TIPRETE d; { d= cel mai mare divizor comun}
SFALGORITM {al numerelor n1 i n2 }
n descrierea multor algoritmi se ntlnete structura repetitiv condiionat pos-
terior:
REPET A PNCND cond SFREP
20 1. Bazele algoritmilor
structur echivalent cu:
A
CTTIMP not (cond) EXECUT A SFCT
Deci ea cere execuia necondiionat a lui A i apoi vericarea condiiei "cond".
Va avea loc repetarea execuiei lui A pn cnd condiia devine adevrat. Deoarece
condiia se veric dup prima execuie a grupului A aceast structur este nu-
mit structura repetitiv condiionat posterior, prima execuie a blocului A ind
necondiionat.
Ca exemplu de algoritm n care se folosete aceast propoziie, vom scrie un al-
goritm pentru aproximarea numrului e cu o precizie dat de numrul eps pozitiv,
folosindu-ne de dezvoltarea n serie:
e = 1 + 1/1! + 1/2! + 1/3! + ... + 1/n! + ...
Specicaia problemei n Pseudocod este:
DATE eps ; { eps>0 }
REZULTATE ve; { aproximarea seriei cu o eroare < eps }
{ deci r= [ e-ve [<eps }
Pentru rezolvarea problemei trebuie s tim c restul r
n
din scrierea
e = 1 + 1/1! + 1/2! + 1/3! +... + 1/n! +... = s
n
+r
n
este mai mic dect ultimul termen adunat la s
n
, deci r
n
< t
n
, unde t
n
= 1/n!
Variabilele auxiliare folosite n descrierea algoritmului sunt:
n - precizeaz ultima fracie adunat;
t - este valoarea acestei fracii.
Exemplul 1.1.4.
ALGORITMUL Nre ESTE: { Calculul lui e cu precizia eps }
CITETE eps; { eps > 0 }
FIE ve:=2.5; t:=0.5; n:=2;
REPET
n:=n+1
t:=t/n;
ve:=ve+t;
PNCND t<eps SFREP
TIPRETE ve;
SFALGORITM
1.1. Descrierea algoritmilor 21
O alt propoziie care cere execuia repetat a unei secvene A este propoziia
PENTRU c:=li; lf [;p] EXECUT A SFPENTRU
Ea denete o structura repetitiv predenit, cu un numr determinat de execuii
ale grupului de propoziii A i este echivalent cu secvena:
c:=li ; nal:=lf ;
REPET
A
c:=c+p
PNCND (c>nal i p>0) sau (c<nal i p<0) SFREP
Se observ c, n sintaxa propoziiei PENTRU, pasul p este nchis ntre paranteze
drepte. Prin aceasta indicm faptul c el este opional, putnd s lipseasc. n cazul
n care nu este prezent, valoarea lui implicit este 1.
Semnicaia propoziiei PENTRU este clar. Ea cere repetarea grupului de
propoziii A pentru toate valorile contorului c cuprinse ntre valorile expresiilor li
i lf (calculate o singur dat nainte de nceperea ciclului), cu pasul p. Se subnelege
c nu trebuie s modicm valorile contorului n nici o propoziie din grupul A. De
multe ori, aceste expresii sunt variabile simple, iar unii programatori modic n A
valorile acestor variabile, nclcnd semnicaia propoziiei PENTRU.
Observaie. Nu recalcula limitele i nu modica variabila de ciclare (contorul) n
interiorul unei structuri repetitive PENTRU.
S observm, de asemenea, c prima execuie a grupului A este obligatorie, abia
dup modicarea contorului vericndu-se condiia de continuare a execuiei lui A.
Ca exemplu, s descriem un algoritm care gsete minimul i maximul componen-
telor unui vector de numere reale.
Vom nota prin X acest vector, deci X = (x
1
, x
2
, ... , x
n
).
Observaie. Vom nota n limbajul Pseudocod componenta x
i
a unui vector cu x[i].
Specicaia problemei este urmtoarea:
DATE n,(x[i] ,i=1,n);
REZULTATE valmin,valmax;
iar semnicaia acestor variabile se nelege din cele scrise mai sus. Pentru rezolvarea
problemei vom examina pe rnd cele n componente. Pentru a parcurge cele n com-
ponente avem nevoie de un contor care s precizeze poziia la care am ajuns. Fie i
acest contor. Avem urmtorul algoritm:
22 1. Bazele algoritmilor
Exemplul 1.1.5.
ALGORITMUL MinMax ESTE: { Calculul }
{ valorii minime i maxime }
CITETE n,( x[i],i=1,n);
FIE valmin:=x[1]; valmax:=x[1];
PENTRU i:=2;n EXECUT
DAC x[i]<valmin
ATUNCI valmin:=x[i]
SFDAC
DAC x[i]>valmax
ATUNCI valmax:=x[i]
SFDAC
SFPENTRU
TIPRETE valmin,valmax;
SFALGORITM
Un rol important n claritatea textului unui algoritm l au denumirile alese pentru
variabile. Ele trebuie s reecte semnicaia variabilelor respective. Deci alege denu-
miri sugestive pentru variabile, care s reecte semnicaia lor. Putem formula astfel
regula de mai jos:
Observaie. Alege denumiri sugestive pentru variabile! n exemplul de mai sus
denumirile valmin i valmax spun clar cititorului ce s-a notat prin aceste variabile.
1.1.4 Calculul efectuat de un algoritm
Fie X
1
, X
2
, ..., X
n
, variabilele ce apar n algoritmul A. n orice moment al execuiei
algoritmului, ecare variabil are o anumit valoare, sau este nc neiniializat.
Vom numi stare a algoritmului A cu variabilele menionate, vectorul s =
(s
1
, s
2
, ..., s
n
) format din valorile curente ale celor n variabile ale algoritmului.
Este posibil ca variabila X
j
s e nc neiniializat, deci s nu aib valoare
curent, caz n care valoarea s
j
este nedenit, lucru notat n continuare prin semnul
ntrebrii ?.
Prin executarea unei anumite instruciuni unele variabile i schimb valoarea, deci
algoritmul i schimb starea.
Se numete calcul efectuat de algoritmul A o secven de stri s
0
, s
1
, s
2
, ..., s
m
unde s
0
este starea iniial cu toate variabilele neiniializate, iar s
m
este starea n
care se ajunge dup execuia ultimei propoziii din algoritm.
1.1. Descrierea algoritmilor 23
Exemplul 1.1.6. Algoritmul Nrdivizori calculeaz numrul de divizori proprii ai
unui numr dat X1.
P1 CITESTE X1;
P2 FIE X2:=1;
P3 FIE X3:=0;
P4 CTTIMP X1 ,= X2 EXECUT
P5 X2:=X2+1;
P6 DAC X1 modulo X2 = 0
ATUNCI X3:=X3+1
SFDAC
SFCT
P7 TIPRETE X1,X3
Presupunnd c X1 = 6, atunci strile prin care trece acest algoritm, deci calculul
efectuat de el, este redat mai jos.
s0 = ( ?, ?, ?)
P1(s0) = s1 = ( 6, ?, ?)
P2(s1) = s2 = ( 6, 1, ?)
P3(s2) = s3 = ( 6, 1, 0)
P5(s3) = s4 = ( 6, 2, 0)
P6(s4) = s5 = ( 6, 2, 1)
P5(s5) = s6 = ( 6, 3, 1)
P6(s6) = s7 = ( 6, 3, 2)
P5(s7) = s8 = ( 6, 4, 2)
P6(s8) = s9 = ( 6, 4, 2)
P5(s9) = s10= ( 6, 5, 2)
P6(s10)= s11= ( 6, 5, 2)
P6(s11)= s12= ( 6, 5, 2)
P5(s12)= s13= ( 6, 6, 2)
P7(s13)= s14= ( 6, 6, 2)
Execuia (calculul) se va ncheia cu tiprirea valorilor 6 i 2 a celor dou variabile
din propoziia P7. Se poate observa c cele dou valori tiprite reprezint, prima
(X1), numrul citit, iar a doua (X3), rezultatul obinut. Rezultatul X3 reprezint
numrul divizorilor proprii ai lui X1.
24 1. Bazele algoritmilor
1.1.5 Ranare n pai succesivi
Adeseori, algoritmul de rezolvare a unei probleme este rezultatul unui proces complex,
n care se iau mai multe decizii. Observaia este adevrat mai ales n cazul prob-
lemelor complicate, dar i pentru probleme mai simple din procesul de nvmnt.
Este vorba de un proces de detaliere pas cu pas a specicaiei problemei, proces de-
numit i proiectare descendent, sau ranare n pai succesivi. Algoritmul apare n
mai multe versiuni succesive, ecare versiune ind o detaliere a versiunii precedente.
n versiunile iniiale apar propoziii nestandard, clare pentru cititor, dar nepre-
cizate prin propoziii standard. Urmeaz ca n versiunile urmtoare s se revin
asupra lor. Algoritmul apare astfel n versiuni succesive, tot mai complet de la o
versiune la alta.
Ca exemplu de algoritm obinut prin ranare succesiv vom proiecta un algoritm
care s rezolve urmtoarea problem:
Exemplul 1.1.7. Se dau numerele ntregi X = (x
1
, x
2
, ..., x
n
). Se cere s se rein
ntr-un vector Y toate componentele distincte ale vectorului X (deci Y are numai
componente distincte).
Specicarea problemei:
DATE n, (x[i], i=1,n);
REZULTATE (y[j], j=1,k); X=Y, unde X este mulimea ce
conine toate numerele x[i], iar Y = mulimea
ce conine pe y[j], j=1,k i y[l] ,= y[j] pentru l ,= j
Variabilele intermediare folosite i semnicaia lor, precum i metoda folosit vor
rezultatul ranrilor succesive i vor nelese din versiunilor respective.
Exemplul 1.1.8.
ALGORITMUL Distinct ESTE: { Versiunea 1 }
CITETE n, (x[i], i=1,n);
FIE y[1]:=x[1]; k:=1;
@Examineaz celelalte numere i dac trebuie adaug-le n Y;
TIPRETE (y[j], j=1,k);
SFALGORITM
Pentru a parcurge celelalte numere avem nevoie de un contor, e el i, i de folosirea
propoziiei PENTRU. Ajungem la varianta:
Exemplul 1.1.9.
ALGORITMUL Distinct ESTE: { Versiunea 2 }
1.1. Descrierea algoritmilor 25
CITETE n, (x[i], i=1,n);
FIE y[1]:=x[1]; k:=1;
PENTRU i:=2;n EXECUT
@Veric dac x[i] aparine mulimii Y;
@Dac nu aparine atunci adaug pe x[i] la Y;
SFPENTRU
TIPRETE (y[j], j=1,k);
SFALGORITM
Decizia ce trebuie luat este cum s vericm apartenena unui elementul x
i
la
mulimea Y format din k elemente. Pentru aceasta calculm indicatorul r, egal cu
0 dac rspunsul este negativ i egal cu 1 n caz contrar. Aceasta se poate face cu
secvena de propoziii:
FIE r:=0; j:=1;
CTTIMP (r=0) i (j<=k) EXECUT
DAC x[i]=y[j]
ATUNCI r:=1;
ALTFEL j:=j+1;
SFDAC
SFCT
Ajungem la versiunea nal a algoritmului dorit:
Exemplul 1.1.10.
ALGORITMUL Distinct ESTE: { Versiunea 3 }
CITETE n, (x[i], i=1,n);
FIE y[1]:=x[1]; k:=1;
PENTRU i:=2;n EXECUT
FIE r:=0; j:=1;
CTTIMP (r=0) i (j<=k) EXECUT
DAC x[i]=y[j]
ATUNCI r:=1;
ALTFEL j:=j+1;
SFDAC
SFCT
DAC r=0
ATUNCI k:=k+1; y[k]:=x[i];
SFDAC
SFPENTRU
26 1. Bazele algoritmilor
TIPRETE (y[j], j=1,k);
SFALGORITM
Rezult ca o consecin, o alt regul important n proiectarea algoritmului:
Observaie. Amn pe mai trziu detaliile nesemnicative; concentreaz-i atenia
la deciziile importante ale momentului.
1.1.6 Probleme propuse
S se descrie n Pseudocod algoritmii pentru rezolvarea urmtoarelor probleme:
1. Se d numrul natural n. S se determine primele n numere prime.
2. Se d n N. S se determine primele n triplete de numere pitagorice. (Tripletul
(i, j, k) constituie numere pitagorice dac i < j < k i i
2
+j
2
= k
2
).
3. Tripletul (z,l,a) reprezint o dat curent zi, lun, an. Determinai a cta zi din
an este aceast dat.
4. Se cunoate data curent (zc,lc,ac) i ziua de natere a unei persoane (zn,ln,an).
Determinai vrsta n zile a acestei persoane.
5. Cunoscnd n ce zi din sptmn a fost 1 ianuarie, determinai ce zi din sp-
tmn va n ziua precizat prin tripletul (z,l,a).
1.1.7 Subalgoritmi
1.1.7.1 Conceptul de subalgoritm
Orice problem poate apare ca o subproblem S a unei probleme mai complexe C.
Algoritmul de rezolvare a problemei S devine n acest caz o parte din algoritmul de
rezolvare a problemei C, parte numit subalgoritm.
Pentru a deni un subalgoritm vom folosi propoziia standard:
SUBALGORITMUL nume(lpf ) ESTE:
unde nume este numele subalgoritmului denit, iar lpf este lista parametrilor for-
mali. Acetia sunt formai din variabilele care marcheaz datele de intrare (cele pre-
supuse cunoscute) i variabilele care marcheaz datele de ieire (rezultatele obinute
de subalgoritm).
Aceast propoziie este urmat de textul efectiv al subalgoritmului, text care pre-
cizeaz calculele necesare rezolvrii subproblemei corespunztoare. Descrierea se va
ncheia cu cuvntul SFSUBALGORITM sau SF-nume.
1.1. Descrierea algoritmilor 27
Exemplul 1.1.11. S considerm ca exemplu un subalgoritm cu numele Maxim,
care determin maximul dintre componentele vectorului X = (x
1
, x
2
, . . . , x
n
).
Datele cunoscute pentru acest subalgoritm sunt vectorul X i numrul n al com-
ponentelor vectorului X. Ca rezultat vom obine maximul cerut, pe care-l vom nota
cu max. n concluzie, specicarea subproblemei este:
DATE n, X;
REZULTATE max;
Deci lista parametrilor formali conine trei variabile, n, X i max. Pentru a gsi
maximul parcurgem toate componentele vectorului X, reinnd n variabila max val-
oarea cea mai mare ntlnit. Evident, trebuie s ncepem cu max = x
1
. Subalgorit-
mul este prezentat n continuare.
SUBALGORITMUL Maxim(n,X,max) ESTE: {Calculeaz valoarea maxim}
{dintre cele n componente ale lui X}
FIE max:=x[1];
PENTRU i:=2;n EXECUT
DAC x[i]>max
ATUNCI max:=x[i];
SFDAC
SFPENTRU
SF-Maxim
Una dintre greelile frecvente ale nceptorilor const n introducerea n corpul
subalgoritmului a unor instruciuni de citire a datelor presupuse cunoscute, sau de
tiprire a rezultatelor obinute. Acest lucru denot o nenelegere a conceptului de
subalgoritm i a rolului subalgoritmilor n programare. Subalgoritmul rezolv o sub-
problem - care e o parte dintr-o problema complex de rezolvat.
De obicei, datele presupuse cunoscute pentru subproblem, nu sunt datele iniiale
cunoscute n problema iniial; ele sunt rezultatul unor calcule efectuate nainte de
apelul subalgoritmului. n general, ele nu sunt cunoscute de programator, ind rezul-
tatul unor calcule fcute de algoritm. Analog, rezultatele obinute de subalgoritm
sunt adesea doar valori intermediare, necesare n continuare, fr a ns obligato-
riu i rezultate ale problemei iniiale. De aceea nu este necesar s le tiprim; este
sarcina algoritmului apelant s trateze rezultatele obinute de subalgoritm cum crede
de cuviin.
Observaie. Evit s citeti i s tipreti date ntr-un subalgoritm.
Excepie de la aceast regul o fac subalgoritmii dedicai citirii unor date, sau
tipririi unor rezultate. n acest caz, citirea, respectiv tiprirea unor date este cerut
28 1. Bazele algoritmilor
expres n enunul subproblemelor corespunztoare. Mai mult, un subalgoritm este
scris pentru a rezolva subproblema corespunztoare indiferent de locul, timpul sau
complexitatea problemei n care este folosit. De aceea, trebuie s concepem subalgo-
ritmii cu gndul la refolosirea lor.
S considerm n cele ce urmeaz, urmtorul exemplu. n cadrul multor algoritmi
este necesar calculul valorilor unei funcii n diferite puncte. Este necesar s denim
funcia printr-un subalgoritm de tip funcie.
Pentru denirea unui subalgoritm de tip funcie se folosete un antet care pre-
cizeaz numele funciei i variabilele de care depinde ea. Subalgoritmul are forma:
FUNCIA nume(lpf) ESTE: {Antetul funciei}
ext {corpul funciei}
SF-nume {marca de sfrit}
n corpul funciei trebuie s existe cel puin o instruciune de atribuire n care
numele funciei apare n membrul stng, deci prin care funcia primete o valoare.
Exemplul 1.1.12. S considerm funcia numar : R {2,3,4,5}, denit matematic
astfel:
numar(x) =
_

_
2, dac x < 0, 2
3, dac 0, 2 x < 0, 5
4, dac 0, 5 0, 9
5, dac x 0, 9
n Pseudocod descrierea este urmtoarea:
FUNCIA numar(x) ESTE:
DAC x<0.2
ATUNCI numar:=2;
ALTFEL
DAC x<0.5
ATUNCI numar:=3;
ALTFEL
DAC x<0.9
ATUNCI numar:=4;
ALTFEL numar:=5;
SFDAC
SFDAC
SFDAC
SF-numar
1.1. Descrierea algoritmilor 29
Am vzut c deniia unei funcii const dintr-un antet i dintr-un bloc care va
deni aciunile prin care se calculeaz valoarea funciei. n antet se precizeaz numele
funciei i lista parametrilor formali.
n concluzie, exist dou categorii de subalgoritmi: de tip funcie i subalgoritmi
propriu-zii, crora li se mai spune i proceduri. Importana lor va subliniat prin
toate exemplele care urmeaz n acest curs. n ncheiere, menionm c subprogramele
de tip funcie se folosesc n scopul denirii funciilor, aa cum sunt cunoscute ele din
matematic, n timp ce subalgoritmii de tip procedur se refer la rezolvarea unor
probleme ce apar ca subprobleme, ind algoritmi de sine stttori.
1.1.7.2 Apelul unui subalgoritm
Am vzut c un subalgoritm este dedicat rezolvrii unei subprobleme S care apare
ntr-o problem mai complex C. Algoritmul corespunztor problemei C va folosi toate
operaiile necesare rezolvrii problemei S, deci va folosi ca parte ntregul subalgoritm
conceput pentru rezolvarea subproblemei S. Spunem c el va apela acest subalgoritm.
n Pseudocod apelul unei funcii se face scriind ntr-o expresie numele funciei
urmat de lista parametrilor actuali. Trebuie s existe o coresponden biunivoc
ntre parametrii actuali i cei formali folosii n deniia funciei. Dei denumirile
variabilelor din cele dou liste pot s difere, rolul variabilelor care se corespund este
acelai. Mai exact, parametrul formal i parametrul actual corespunztor trebuie
s se refere la aceeai entitate, trebuie s aib aceeai semnicaie, s reprezinte
aceeai structur de date. Putem considera c n timpul execuiei algoritmului cei doi
parametri devin identici.
Folosirea unui subalgoritm n cadrul unui algoritm se face apelnd acest subalgo-
ritm prin propoziia standard:
CHEAM nume(lpa);
unde nume este numele subalgoritmului apelat, iar lpa este lista parametrilor ac-
tuali. Aceast list conine toate datele de intrare (cele cunoscute n subproblema
corespunztoare) i toate rezultatele obinute n subalgoritm. i n acest caz ntre
lista parametrilor formali din deniia subalgoritmului i lista parametrilor actuali
din propoziia de apel trebuie s existe o coresponden biunivoc, ca i n cazul
funciilor.
Ca o prim vericare a respectrii acestei corespondene, subliniem c numrul
parametrilor actuali trebuie s coincid cu numrul parametrilor formali.
Ca exemplu de apelare a funciilor, prezentm n continuare un algoritm pentru
a calcula a cta zi din anul curent este ziua curent (zi,luna,an). El folosete un
30 1. Bazele algoritmilor
subalgoritm de tip funcie pentru a obine numrul zilelor lunii cu numrul de ordine
i i un altul pentru a verica dac un an este bisect sau nu. Aceste dou funcii sunt:
- NRZILE(i) furnizeaz numrul zilelor existente n luna i a unui an nebisect;
- BISECT(an) adevrat dac anul dintre paranteze este bisect.
Exemplul 1.1.13.
ALGORITMUL NUMR_ZILE ESTE: {A cta zi dintr-un an?}
CITETE zi, luna, an; {introducei data curent}
FIE nr:=zi; {nr va numrul care reprezint a cta zi }
{din an este data curent}
DAC luna>1 ATUNCI
PENTRU i:=1; luna-1 EXECUT
nr:=nr+NRZILE(i);
SFPENTRU
SFDAC
DAC luna>2 ATUNCI
DAC BISECT(an) ATUNCI
nr:=nr+1;
SFDAC
SFDAC
TIPRETE nr;
SFALGORITM
S observm c n proiectarea acestui algoritm nu este necesar s cunoatem deta-
liat subalgoritmii folosii, ci doar specicarea acestor subalgoritmi, numele lor i lista
parametrilor formali. La acest nivel accentul trebuie s cad pe proiectarea algorit-
mului apelant, urmnd s se revin ulterior la proiectarea subalgoritmilor apelai,
conform specicaiei acestora. n cazul de fa este necesar descrierea funciilor
NRZILE(i) i BISECT(an). Lsm aceast descriere ca exerciiu pentru cititor.
Exemplul 1.1.14. Un alt exemplu de apelare a unei proceduri este algoritmul care
efectueaz suma a dou polinoame. Un polinom P(X) este determinat prin gradul su,
m, i prin vectorul coecienilor P = (p
0
, p
1
, . . . , p
m
) (prin p
i
s-a notat coecientul
lui X
i
).
Procedura SUMAPOL(m,P,n,Q,r,S) trebuie s efectueze suma S(X) =
P(X)+Q(X), unde P este un polinom de gradul m, iar Q este un polinom de gradul
n, date. Suma lor, S, va un polinom de gradul r calculat de subalgoritm. Pentru
efectuarea acestui calcul este util folosirea unui alt subalgoritm care adun la suma
1.2. Elaborarea algoritmilor. Propoziii nestandard 31
S(X) un alt polinom, T(X), de grad mai mic sau egal dect gradul polinomului S(X).
Un astfel de subalgoritm se prezint n continuare.
SUBALGORITMUL SUMAPOL1(n,T,r,S) ESTE: { n r}
{S(X):=S(X)+T(X)}
PENTRU i:=0;n EXECUT
s[i] := s[i]+t[i];
SFPENTRU
SF-SUMAPOL1
Subalgoritmul SUMAPOL apeleaz acest subalgoritm, aa cum se poate vedea n
continuare.
SUBALGORITMUL SUMAPOL(m,P,n,Q,r,S) ESTE: {S(X):=P(X)+Q(X)}
DAC m<n
ATUNCI r:=n; S:=Q;
CHEAM SUMAPOL1(m,P,r,S)
ALTFEL r:=m; S:=P;
CHEAM SUMAPOL1(n,Q,r,S)
SFDAC
SF-SUMAPOL
S observm c n textul acestui subalgoritm am extins semnicaia propoziiei de
atribuire, permind atribuirea S:=Q. Acest lucru este normal ntruct S corespunde
unui polinom, iar Q este un polinom cunoscut; prin atribuire S primete o valoare
iniial, cea dat de polinomul Q.
Subliniem c atribuirea v := u va corect n cazul n care variabilele u i v
reprezint aceleai obiecte matematice, deci au aceeai semnicaie.
1.2 Elaborarea algoritmilor. Propoziii nestandard
Prin elaborarea (proiectarea) unui algoritm nelegem ntreaga activitate depus de la
enunarea problemei pn la realizarea algoritmului corespunztor rezolvrii acestei
probleme.
n elaborarea unui algoritm deosebim urmtoarele activiti importante [And,
1995]:
specicarea problemei;
descrierea metodei alese pentru rezolvarea problemei;
32 1. Bazele algoritmilor
proiectarea propriu-zis. Ea const n descompunerea problemei n subprob-
leme, obinerea algoritmului principal i a tuturor subalgoritmilor apelai, con-
form metodelor prezentate n seciunile urmtoare. Ea se termin cu descrierea
algoritmului principal i a subalgoritmilor menionai, dar i cu precizarea denu-
mirilor i semnicaiilor variabilelor folosite;
vericarea algoritmului obinut.
Astfel, s considerm urmtorul exemplu, calculul radicalului de ordinul 2 din x.
a. n partea de specicare a problemei vom meniona:
Se d un numr real notat prin x, care trebuie s e nenegativ. Se cere s gsim
un alt numr pozitiv r astfel nct

x = r.
Vom folosi un algoritm de aproximare a lui r. Deci specicarea fcut nu este com-
plet, neputnd gsi un algoritm care s rezolve direct problema n forma enunat.
Vom modica aceast specicare, cernd s se calculeze r aproximativ, cu o eroare
ce nu depete un numr real pozitiv eps prestabilit. Ajungem astfel la urmtoarea
specicare:
DATE eps,x; { eps,x R, eps>0 i x 0 }
REZULTATE r; { [r

x[ < eps }
b. Urmeaz s precizm metoda de rezolvare a problemei. Se tie c exist mai multe
metode de calcul a radicalului. Menionm urmtoarele dou posibiliti:
- ca limit a unui ir convergent la r (denit printr-o relaie de recuren);
- prin aproximarea soluiei ecuaiei

x = r.
Alegem pentru exemplicare metoda a doua, deci l vom calcula pe r rezolvnd
ecuaia

x = r.
a
r
(b, f(b))
a
b b
(a, f(a))
Figura 1.2: Grac pentru metoda coardei i a tangentei
1.2. Elaborarea algoritmilor. Propoziii nestandard 33
Pentru rezolvarea ecuaiei generale f(x) = 0 exist mai multe metode. Alegem
pentru rezolvare metoda coardei i a tangentei.
Aceast metod const n micorarea repetat a intervalului [a,b] care conine
rdcina r cutat, la intervalul [a,b], aa cum se poate vedea n Figura 1.2. Vari-
abilele folosite n descrierea algoritmului sunt:
a i b, reprezentnd capetele intervalului n care se a rdcina;
r mijlocul intervalului (a,b) n momentul n care b-a < eps, deci valoarea cutat.
Algoritmul propriu-zis (secvena de propoziii care obine rezultatele dorite
pornind de la datele iniiale) este descris n continuare:
Exemplul 1.2.1. {Algoritmul: Metoda coardei}
@Iniializeaz pe a i b;
REPET
@Atribuie lui a abscisa punctului de intersecie a axei OX cu coarda ce
unete punctele (a,f(a)) i (b,f(b));
@Atribuie lui b abscisa punctului de intersecie a axei OX cu tangenta n
punctul (b,f(b)) dus la graculfunciei f(t) =

t x;
PNCND b-a<eps SFREP
FIE r:=(a+b)/2;
n textul de mai sus apar trei propoziii nestandard care sugereaz ns foarte
bine ce aciuni trebuiesc ntreprinse. Prima stabilete intervalul iniial n care se a
rdcina, care depinde de mrimea lui x: (x,1) cnd x este mai mic dect 1 sau (1,x)
n caz contrar. Deci ea se va transcrie n propoziia standard:
DAC x<1
ATUNCI a:=x; b:=1;
ALTFEL a:=1; b:=x;
SFDAC
Celelalte dou propoziii nestandard se vor transcrie n propoziiile standard:
FIE a := E1; b := E2 ;
unde E1 este expresia care reprezint abscisa punctului de intersecie a axei OX
cu coarda ce unete punctele (a, f(a)) i (b,f(b)), iar E2 este expresia care reprezint
abscisa punctului de intersecie a axei OX cu tangenta n punctul (b, f(b)) dus la
gracul funciei f(t) =

t x.
Se ajunge la urmtoarea variant nal:
Exemplul 1.2.2.
ALGORITMUL Extrageradical ESTE: { Radical }
{ r := radical din x }
34 1. Bazele algoritmilor
CITESTE eps,x; { eps, x R, eps>0 i x 0 }
DAC x<1
ATUNCI a:=x; b:=1; { Iniializeaz }
ALTFEL a:=1; b:=x; { pe a i b }
SFDAC
REPET
a := E1; {abscisa punctului de intersecie a axei OX cu}
{coarda ce unete punctele (a,f(a)) i (b,f(b))}
b := E2; {abscisa punctului de intersecie a axei OX cu tangenta}
{ n punctul (b,f(b)) dus la gracul funciei f(t) = t2-x }
PNCND b-a<eps SFREP
FIE r:=(a+b)/2;
TIPRETE r; { [ r-rad(x) [<eps }
SF-Extrageradical
1.3 Proiectarea ascendent i proiectarea descen-
dent
Exist dou metode generale de proiectare a algoritmilor, a cror denumire provine
din modul de abordare a rezolvrii problemelor: metoda descendent i metoda ascen-
dent. Proiectarea descendent (top-down) pornete de la problema de rezolvat, pe
care o descompune n pri rezolvabile separat. De obicei, aceste pri sunt subprob-
leme independente, care la rndul lor pot descompuse n subprobleme. La prima
descompunere accentul trebuie pus pe algoritmul (modulul) principal nu asupra sub-
problemelor. La acest nivel nu ne intereseaz amnunte legate de rezolvarea subprob-
lemelor, presupunem c le tim rezolva, eventual c avem deja subalgoritmii pentru
rezolvarea lor. Urmeaz s considerm pe rnd, ecare subproblem n parte i s
proiectm (n acelai mod) un subalgoritm pentru rezolvarea ei. n nal, se va descrie
subalgoritmul de rezolvare al ecrei subprobleme, dar i interaciunile dintre aceti
subalgoritmi i ordinea n care ei sunt folosii.
Noiunea de modul va denit n seciunea urmtoare. Deocamdat nelegem
prin modul orice subalgoritm sau algoritmul principal. Legtura dintre module se
prezint cel mai bine sub forma unei diagrame numit arbore de programare [Bla,
1978]. Fiecrui modul i corespunde n arborele de programare un nod, ai crui
descendeni sunt toate modulele apelate direct. Nodul corespunztor algoritmului
principal este chiar nodul rdcin.
1.3. Proiectarea ascendent i proiectarea descendent 35
Astfel, n arborele de programare din Figura 1.3 exist un algoritm principal (modu-
lul PRINC), care apeleaz trei subalgoritmi (modulele CITDATE, CALCULE i
TIPREZ). La rndul su, modulul CALCULE apeleaz trei subalgoritmi (modulele
M1, M2 i M3).
PRINC
CALCULE TIPREZ CITDATE
M
2
M
3 M
1
Figura 1.3: Arbore de programare
Din arborele de programare nu reiese ns de cte ori se apeleaz un subalgoritm,
sau dac doi subalgoritmi se exclud unul pe cellalt. Este posibil nlocuirea arborelui
de programare cu o diagram de structur construit pe concepia NESTED-LOGIC.
n construirea unei astfel de diagrame se folosesc structurile din Figura 1.4, bazate pe
urmtoarele reguli [Liv, 1986]:
a) Operaia de trecere de la un nivel superior la unul inferior se interpreteaz prin
expresia "CONST DIN" (g. 1.4 a);
b) Operaia de trecere de la un bloc la altul de pe acelai nivel se interpreteaz cu
expresia "URMAT DE" (g. 1.4 a);
c) Caracterul o prezent n bloc n colul din dreapta sus este descendentul unui
bloc de tip selectiv (g 1.4.b);
d) Caracterul * prezent n bloc n colul din dreapta sus identic un bloc repet-
itiv i se interpreteaz cu expresia "MAI MULTE" (g.1.4 c).
A

X
A B
X
A B
X
(a) (b) (c)
Figura 1.4: Diagrame de structur construit pe concepia NESTED-LOGIC
Teorema de structur NESTED-LOGIC arm c oricare ar schema logic S
exist o schem S de structur NESTED-LOGIC echivalent cu S (deci care rezolv
36 1. Bazele algoritmilor
aceeai problem).
Ca exemplu de proiectare descendent, descriem n continuare un algoritm pentru
rezolvarea unui sistem liniar de n ecuaii cu n necunoscute:
A*X = B
La primul nivel de descompunere deosebim trei activiti distincte:
- citirea datelor problemei;
- rezolvarea sistemului menionat;
- tiprirea rezultatelor.
Pentru rezolvarea sistemului vom proiecta un subalgoritm, ntruct aceast pro-
blem poate apare adesea ca subproblem i dorim s refolosim subalgoritmul obinut.
Pentru rezolvarea sistemului identicm dou subprobleme independente:
- reducerea sistemului, prin metoda lui Gauss, la un sistem triunghiular echivalent;
- rezolvarea sistemului triunghiular obinut.
Mai mult, subproblema reducerii sistemului conine ca subprobleme determinarea
ecuaiei n care rmne x
i
i care este folosit la reducerea acestei necunoscute din
celelalte ecuaii, schimbarea a dou ecuaii ntre ele, deci interschimbarea a dou
linii din matricea extins i eliminarea propriu-zis. Subalgoritmul PIVOT, cores-
punztor primei subprobleme, determin care dintre ecuaiile de rang i, i + 1, ..., n
are coecientul lui x
i
maxim n valoare absolut, caz n care erorile introduse din
cauza aproximrilor n calcule cu numere reale sunt minime. Subalgoritmii INTER-
SCHIMB i ELIMIN corespund celorlalte dou subprobleme. Arborele de programare
corespunztor se d n Figura. 1.5.
REZISTEM
SISTEM TIPSOL CITSIST
INTERSCHIMB ELIMIN PIVOT
REDUTRI REZOLV
Figura 1.5: Arborele de programare pentru rezolvarea sistemului
1.3. Proiectarea ascendent i proiectarea descendent 37
Exemplul 1.3.1.
ALGORITMUL REZSISTEM ESTE:
Cheam CITSISTEM(n, A, B);
Cheam SISTEM(n, A, B, kod);
DAC kod = 1 ATUNCI Cheam TIPSOL(n, B);
ALTFEL TIPRETE "Sistemul nu este compatibil determinat.";
SFDAC
SF-REZSISTEM
Subalgoritmul SISTEM pentru rezolvarea unui sistem liniar de n ecuaii cu n ne-
cunoscute este prezentat n continuare.
SUBALGORITMUL SISTEM(n,A,B,kod) ESTE:
{Rezolv sistemul AX=B, de n ecuaii cu n necunoscute}
{A este matricea sistemului, B vectorul termenilor liberi i}
{Soluia se depune n vectorul B, iar A se distruge}
{kod = 1 pentru sistem compatibil, altfel kod = 0 }
CHEAM REDUTRI(n,A,B,kod);
{Reduce sistemul la un sistem triunghiular echivalent}
DAC kod = 1 ATUNCI {kod = 1 cnd sistemul e compatibil}
CHEAM REZOLV(n,A,B,kod); {Rezolv sistemul triunghiular}
SFDAC {Soluia se depune n vectorul B}
SF-SISTEM
SUBALGORITMUL REDUTRI(n,A,B,kod) ESTE: {Reduce sistemul liniar
A.X=B, de n ecuaii cu n necunoscute la un sistem triunghiular echivalent}
{ A.X = B, matricea A avnd sub diagonal numai zerouri}
{A este matricea sistemului iar B - vectorul termenilor liberi}
{kod = 0 pentru sistem nedeterminat sau incompatibil}
FIE kod:=1; {Ipoteza sistem determinat}
i:=1;
CTTIMP (i<n) I (kod=1) EXECUT {Se reduce necunoscuta x
i
din ecuaiile
i+1,...,n}
CHEAM PIVOT(n,A,i,j);
{j = numrul ecuaiein care se pstreaz necunoscuta x[j] }
DAC a[i,j]=0
ATUNCI kod:=0 ALTFEL
DAC j>i
38 1. Bazele algoritmilor
ATUNCI CHEAM INTERSCHIMB(i,j,n,A,B)
SFDAC
CHEAM ELIMIN(n,A,B,i);
SFDAC
FIE i:=i+1;
SFCT
SF-REDUTRI
SUBALGORITMUL REZOLV(n,A,B,ind) ESTE: {Rezolva sistemul triunghiular
A.X=B}
{deci matricea A are sub diagonala}
{numai zerouri. ind=1 pt.sistem determinat}
{in care caz solutia se pune in vectorul B}
{si ind=0 dac e nedeterminat sau incompatibil}
FIE r1:=b[n]; ind:=1;
DAC a[n,n]=0
ATUNCI ind:=0
ALTFEL b[n]:=r1/a[n,n]
SFDAC
FIE i:=n-1;
CTTIMP (ind=1) I (i>=1) EXECUT
DAC a[i,i]=0
ATUNCI ind:=0
ALTFEL
r1:=b[i];
PENTRU k:=i+1,n EXECUT
r:=a[i,k]*b[k]; r1:=r1-r;
SFPENTRU
b[i]:= r1/a[i,i]
SFDAC
Fie i:=I-1
SFCT
SF-REZOLV
SUBALGORITMUL PIVOT(n,A,i,j) ESTE: {j primete o valoare >=i pentru }
FIE j:=i; { care a[j,i] e maxim n valoare absolut}
PENTRU l:=i+1, n EXECUT
DAC a[l,i] > a[j,i]
1.3. Proiectarea ascendent i proiectarea descendent 39
ATUNCI j:=l
SFDAC
SFPENTRU
SF-PIVOT
SUBALGORITMUL INTERSCHIMB(i,j,n,A,B) ESTE:
{Schimb ntre ele liniile i i j din matricea A}
{ de ordinul n i termenii liberi corespunztori}
PENTRU l:=1; n EXECUT
r:=a[i,l]; a[i,l]:=a[j,l]; a[j,l]:=r
SFPENTRU
FIE r:=b[i]; b[i]:=b[j]; b[j]:=r
SF-INTERSCHIMB;
SUBALGORITMUL ELIMIN(n,A,B,i) ESTE: {Elimin necunoscuta x[i] din
ecuaiile i+1,...,n}
FIE r:=a[i,i]; { x[i] din ecuaiile n ipoteza a[i,i] ,= 0}
PENTRU k:=i,n EXECUT {Imparte ecuaia nr i cu r}
FIE a[i,k]:=a[i,k]/r
SFPENTRU
FIE b[i] := b[i]/r
PENTRU j:=i+1,n EXECUT {Elimin necunoscuta}
FIE r:=a[j,i]; {x[i] din ecuaia nr.j}
PENTRU k:=1,n EXECUT
a[j,k]:=a[j,k]-r*a[i,k];
SFPENTRU
FIE b[j]:=b[j]-r*b[i]
SFPENTRU
SF-ELIMIN
n multe cri metoda top-down este ntlnit i sub denumirea stepwise-renement,
adic ranare n pai succesivi. Este vorba de un proces de detaliere pas cu pas a
specicaiei, denumit proiectare descendent. Algoritmul apare n diferite versiuni
succesive, ecare ind o detaliere a versiunii precedente. n aceste versiuni succesive
apar multe enunuri nestandard ce urmeaz a precizate treptat prin propoziii
standard. Se recomand ca ele s rmn comentarii n versiunea nal. Algoritmul
apare n versiuni succesive, tot mai complet de la o versiune la alta. n versiunea
nal n algoritm apar numai propoziii standard.
40 1. Bazele algoritmilor
Diferena ntre metoda top-down i metoda ranrii succesive este neesenial,
scopul urmrit ind acelai: concentrarea ateniei asupra prilor importante ale mo-
mentului i amnarea detaliilor pentru mai trziu. Dac ar necesar s le deosebim
am spune c metoda top-down se refer la nivelul macro iar metoda ranrii succesive
la nivelul micro. La nivel macro se dorete descompunerea unei probleme complexe n
subprobleme. La nivel micro se dorete obinerea unui modul n versiune nal. ntr-o
versiune intermediar pot prezente numai prile importante ale acestuia, urmnd
s se revin asupra detaliilor n versiunile urmtoare, dup ce aspectele importante
au fost rezolvate.
Avantajele proiectrii top-down (cunoscut i sub denumirea "Divide et impera")
sunt multiple. Avantajul principal const n faptul c ea permite programatorului s
reduc complexitatea problemei, subproblemele n care a fost descompus ind mai
simple, i s amne detaliile pentru mai trziu. n momentul n care descompunem
problema n subprobleme nu ne gndim cum se vor rezolva subproblemele ci care sunt
ele i conexiunile dintre ele.
Proiectarea descendent permite lucrul n echipe mari. Prin descompunerea pro-
blemei n mai multe subprobleme, ecare subproblem poate dat spre rezolvare
unei subechipe. Fiecare subechip nu cunoate dect subproblema pe care trebuie s
o rezolve.
Metoda "Divide et Impera" poate folosit nu numai la mprirea problemei n
subprobleme ci i la mprirea datelor n grupe mai mici de date [Cri, 1993].
Metoda ascendent (bottom-up) pornete de la propoziiile limbajului i de la
subalgoritmi existeni, pe care i asambleaz n ali subalgoritmi pentru a ajunge n
nal la algoritmul dorit. Cu alte cuvinte, n cazul metodei ascendente va scris
mai nti subalgoritmul apelat i apoi cel care apeleaz. Ca rezultat al proiectrii
ascendente se ajunge la o mulime de subalgoritmi care se apeleaz ntre ei. Este
important s se cunoasc care subalgoritm apeleaz pe care, lucru redat printr-o
diagram de structur, ca i n cazul programrii descendente.
Aceast metod are marele dezavantaj c erorile de integrare vor detectate
trziu, abia n faza de integrare. Se poate ajunge abia acum la concluzia c unii
subalgoritmi, dei coreci, nu sunt utili.
De cele mai multe ori nu se practic o proiectare ascendent sau descendent pur
ci o combinare a lor, o proiectare mixt [Ski, 1997].
1.4. Proiectarea modular 41
1.4 Proiectarea modular
Prin proiectare (programare) modular nelegem metoda de proiectare (programare)
a unui algoritm pentru rezolvarea unei probleme prin folosirea modulelor.
Dar ce este un modul? Modulul este considerat [Fre, 1986] o unitate structural
de sine stttoare, e program, e subprogram, e o unitate de program. Un modul
poate conine sau poate coninut ntr-alt modul. Un modul poate format din mai
multe submodule. Astfel, n Pseudocod, ecare subalgoritm i algoritmul principal
sunt considerate module. n limbajele de programare cu structur de bloc, de exemplu
n Turbo Pascal, UNIT-urile pot considerate module. La compilarea separat un
grup de subprograme compilate deodat constituie un modul, dar acest modul poate
considerat ca o mulime de submodule din care este compus.
Este ns important ca ecare modul s-i aib rolul su bine precizat, s realizeze
o funcie n cadrul ntregului program. El apare n mod natural n descompunerea
top-down.
Indiferent c privim modulul ca un singur subalgoritm, un grup de subalgoritmi,
sau un algoritm de sine stttor ce apeleaz ali subalgoritmi, considerm modulele
relativ independente, dar cu posibiliti de comunicare ntre ele. Astfel, un modul nu
trebuie s e inuenat de maniera n care se lucreaz n interiorul altui modul. Orice
modicare ulterioar n structura unui program, dac funcia pe care o realizeaz un
modul M nc este necesar, acest modul trebuie s e util i folosit n continuare
fr modicri.
Rezult c programarea modular se bazeaz pe descompunerea problemei n sub-
probleme i proiectarea i programarea separat a subalgoritmilor corespunztori. De
altfel, considerm c ntr-o programare serioas nu se poate ajunge la implementare
fr a avea n prealabil algoritmii descrii ntr-un limbaj de descriere (la noi Pse-
udocod). Deci programarea modular se refer n primul rnd la proiectarea mo-
dular a algoritmilor i apoi la traducerea lor n limbajul de programare ales, innd
seama de specicul acestui limbaj. Programarea modular este strns legat de pro-
gramarea ascendent i de programarea descendent, ambele presupunnd folosirea
subalgoritmilor pentru toate subproblemele ntlnite.
Avantajele programrii modulare sunt multiple. Menionm n cele ce urmeaz
cteva dintre ele [Sed, 1988]:
Descompunerea unei probleme complexe n subprobleme este un mijloc conve-
nabil i ecient de a reduce complexitatea (Principiul Divide et impera
acioneaz i n programare). Este evident c probabilitatea apariiei erorilor n
conceperea unui program crete cu mrimea programului, lucru conrmat i de
42 1. Bazele algoritmilor
experiena practic. De asemenea, rezolvnd o problem mai simpl, testarea
unui modul se poate face mult mai uor dect testarea ntregului algoritm.
Apoi, faptul c trebuiesc proiectate mai multe subprograme pentru subprob-
lemele ntlnite, permite munca mai multor programatori. S-a ajuns astfel la
munca n echip, modalitate prin care se ajunge la scurtarea termenului de
realizare a produsului program.
Modulele se pot refolosi ori de cte ori avem nevoie de ele. Astfel, s-a ajuns la
compilarea separat a subprogramelor i la pstrarea subprogramelor obinute
n biblioteci de subprograme, de unde ele se pot refolosi la nevoie. Sunt cunos-
cute astzi multe astfel de biblioteci de subprograme. Reutilizabilitatea acestor
subprograme este o proprietate foarte important n activitatea de programare.
Ea duce la mrirea productivitii n programare, dar i la creterea siguranei
n realizarea unui produs corect.
Uneori, n timpul proiectrii algoritmului sau a implementrii lui, se ajunge la
concluzia c proiectarea a fost incomplet sau c unele module sunt ineciente.
i n aceast situaie programarea modular este avantajoas, ea permind
nlocuirea modulului n cauz cu altul mai performant.
Una din activitile importante n realizarea unui program este vericarea corec-
titudinii acestuia [Liv, 1980]. Experiena a artat c modulele se pot verica cu att
mai uor cu ct sunt mai mici. Abilitatea omului de a nelege i analiza corectitudinea
unui subalgoritm este mult mai mare pentru texte scurte. n unele cri chiar se re-
comand a nu se folosi subalgoritmi mai mari dect 50 de propoziii. Sigur c o astfel
de limit nu exist, dar se recomand descompunerea unui subalgoritm n ali subal-
goritmi oricnd acest lucru este posibil n mod natural, deci aceti noi subalgoritmi
rezolv subprobleme de sine stttoare, sau realizeaz funcii bine denite.
Ca exemplu de proiectare modular, ne propunem s prezentm un algoritm pen-
tru rezolvarea urmtoarei probleme:
Exemplul 1.4.1. Dirigintele unei clase de elevi dorete s obin un clasament al
elevilor n funcie de media general. n plus, pentru ecare disciplin n parte, dorete
lista primilor ase elevi [Alb, 1994].
n rezolvarea acestei probleme este necesar gsirea ordinii n care trebuiesc tiprii
elevii n funcie de un anumit rezultat: nota la disciplina "j", sau media general. Am
identicat prin urmare dou subprobleme independente, referitoare la:
(1) aarea ordinii n care trebuie tiprite n numere pentru a le obine ordonate;
1.4. Proiectarea modular 43
(2) tiprirea elevilor clasei ntr-o anumit ordine.
Prima subproblem se poate specica astfel:
Dndu-se numerele x
1
, x
2
, ..., x
n
, gsii ordinea o
1
, o
2
, ..., o
n
, n care aceste numere
devin ordonate descresctor, adic
x[o
1
]x[o
2
]...x[o
n
].
Pentru rezolvarea ei vom pezenta un subalgoritm ORDINE n care intervin trei
parametri formali:
- n, numrul valorilor existente;
- X, vectorul acestor valori;
- O, vectorul indicilor care dau ordinea dorit.
Primii doi parametrii marcheaz datele presupuse cunoscute, iar al treilea, rezul-
tatele calculate de subalgoritm.
SUBALGORITMUL ORDINE(n,X,O) ESTE: {n, numrul valorilor existente; X,
vectorul acestor }
{ valor; O, vectorul indicilor care dau ordinea dorit }
PENTRU i:=1; n EXECUT
O[i] :=i;
SFPENTRU
REPET ind:=0;
PENTRU i:=1;n-1 EXECUT
DAC x[O[i]] < x[O[i+1]] ATUNCI
FIE ind:=1; t:=O[i+1] ;
O[i+1]:=O[i]; O[i] :=t;
SFDAC
SFPENTRU
PANCND ind=0 SFREP
SF-ORDINE
A doua subproblem se poate specica astfel:
Dndu-se ordinea o
1
, o
2
, ..., o
n
, a elevilor clasei, numele i mediile acestora, s se
tipreasc numele i mediile primilor k elevi n ordinea specicat.
Subalgoritmul TIPAR, dat n continuare, rezolv aceast problem.
44 1. Bazele algoritmilor
SUBALGORITMUL TIPAR(k, NUME, O) ESTE:
PENTRU i:=1;k EXECUT
@Tiprete datele elevului de rang o
i
;
SFPENTRU
SF-TIPAR
Variabilele folosite pentru problema dat sunt urmtoarele:
- n reprezint numrul elevilor clasei;
- m este numrul disciplinelor la care elevii primesc note;
- NUME este vectorul care reine numele elevilor: NUME[i] este numele elevului
cu numrul de ordine i;
- NOTE este matricea notelor elevilor, avnd n linii i m coloane;
NOTE[i,j] este nota elevului cu numele NUME[i] la disciplina cu numrul de ordine
j;
NOTE[j] este coloana a j-a a matricei NOTE i reprezint notele elevilor la disciplina
j;
- MEDII este vectorul mediilor generale.
Algoritmul este:
ALGORITMUL CLASAMENT ESTE: { Ordonare }
CITETE m, {numrul disciplinelor i}
n, {al elevilor}
NUME[i], i=1,n, {numele elevilor}
NOTE[i,j], j=1,m, i=1,n; {notele elevilor}
PENTRU i:=1;n EXECUT { calculeaz media general}
FIE S:=0; {a elevului i}
PENTRU j:=1;m EXECUT
S:=S+NOTE[i,j];
SFPENTRU
FIE MEDII[i]:=S/m;
SFPENTRU
CHEAM ORDINE(n,MEDII,O);
CHEAM TIPAR(n,NUME,O);
PENTRU j:=1;m EXECUT
CHEAM ORDINE(n,NOTE.j,O);
CHEAM TIPAR(n,NUME,O);
SFPENTRU
1.4. Proiectarea modular 45
SF-ALGORITM
ntr-un algoritm, parametrii formali i actuali pot funcii sau proceduri. n
continuare, este prezentat un astfel de exemplu, n care se calculeaz radicalii de
ordinul doi i trei din constanta mm rezolvnd ecuaiile:
x
2
- mm = 0, notat g(x) = 0,
respectiv
x
3
- mm = 0, notat h(x) = 0.
Pentru rezolvarea unei ecuaii se pot folosi mai multe metode. n program am
ales dou: metoda njumtirii i metoda coardei. Metoda coardei este descris
amnunit n seciunea urmtoare. Metoda njumtirii const n njumtirea
intervalului [a,b] care conine rdcina i reinerea aceluia n care se a rdcina,
subinterval care va noua valoare a lui [a,b]. Calculul se ncheie n momentul n care
lungimea intervalului [a,b] este mai mic dect , care ne d eroarea cu care dorim s
am rdcina.
ntruct metoda coardei folosete i prima derivat, am notat prin f1, respectiv g1
derivatele funciilor f i g. Prin c i t s-au notat cele dou extremiti ale intervalului
care conine rdcina, t ind extremitatea n care se duce tangenta [Ata, 1996].
SUBALGORITMUL coarda(c,t,r,f,f1) ESTE: {Se rezolv ecuaia f(x)=0 prin
metoda coardei}
{c,t sunt extremitile intervalului care conine}
{rdcina, iar f1este derivata lui f }
{r este rdcina care se calculeaz}
REPET
c:=c-f(c)*(t-c)/(f(t)-f(c));
t:=t-f(t)/f1(t);
PNCND [t c[ < 0.00001;
FIE r:=(c+t)/2;
SF-coarda
SUBALGORITMUL juma(a,b, r, f,f1) ESTE: {Se rezolv prin metoda n-
jumtirii}
{ecuaia f(x)=0, care are o rdcin n [a,b]}
{r= rdcina obinut, iar f1 este derivata lui f}
REPET
r:=(a+b)/2;
DAC f(a)*f(r) <0 ATUNCI
b:=r;
46 1. Bazele algoritmilor
ALTFEL
a:=r;
SFDAC
PNCND [b a[ < .00001 SFREPET
SF-juma
SUBALGORITMUL Rezec(a,b, r, f,f1, met) ESTE:
CHEAM met(a,b,r,f,f1);
SF-Rezec
ALGORITMUL punctii ESTE:
TIPRETE njumtire Coarda ;
CHEAM Rezec(1,2,rj,g,g1,juma);
CHEAM Rezec(1,2,rc,g,g1,coarda);
TIPRETE rj,rc ;
CHEAM Rezec(1,2,rj,h,h1,juma);
CHEAM Rezec(1,2,rc,h,h1,coarda);
TIPRETE rj,rc ;
SFALGORITM
1.5 Apel recursiv
n exemplele anterioare se observ c apelul unui subprogram se face dup ce el a fost
denit. Este ns posibil ca un subalgoritm s se apeleze pe el nsui. ntr-un astfel de
caz, spunem c apelul este recursiv, iar subalgoritmul respectiv este denit recursiv.
Ca exemplu, denim n continuare o funcie care calculeaz recursiv valoarea n!.
Se va folosi formula:
n! =
_
_
_
n (n 1)!, n > 0
1, n = 0
Recursivitatea const n faptul c n deniia funciei Factorial n argumentul n se
folosete aceeai funcie Factorial dar de argument n-1. Deci, funcia Factorial se
apeleaz pe ea nsi. Este important ca numrul apelurilor s e nit, deci ca
procedeul de calcul descris s se termine.
FUNCTIA Factorial(n) ESTE:
DAC n=0 ATUNCI
Factorial:=1;
1.7. Probleme propuse 47
ALTFEL
Factorial:= n*Factorial(n-1);
SFDAC
SF-Factorial;
1.6 Programarea structurat
Programarea structurat este un stil de programare aprut n urma experienei primi-
lor ani de activitate. Ea cere respectarea unei discipline de programare i folosirea
riguroas a ctorva structuri de calcul. Ca rezultat se va ajunge la un algoritm uor
de urmrit, clar i corect [Baa, 1987].
Termenul programare, folosit n titlul acestei seciuni i consacrat n literatura
de specialitate, este folosit aici n sens larg i nu este identic cu cel de programare
propriu-zis. Este vorba de ntreaga activitate depus pentru obinerea unui program,
deci att proiectarea algoritmului ct i traducerea acestuia n limbajul de programare
ales.
Bohm i Jacopini [Bh, 1966] au demonstrat c orice algoritm poate compus din
numai trei structuri de calcul:
- structura secvenial;
- structura alternativ;
- structura repetitiv.
1.7 Probleme propuse
I. Descriei n Pseudocod subalgoritmi care calculeaz urmtoarele funcii:
1. Pentru n N funcia Prim(n) calculeaz al n-lea numr prim.
2. Pentru z, l, a N dai, 1 z 31, 1 l 12, 1900 < a, funcia NRZI(z, l, a)
spune a cta zi din anul a este data (z, l, a);
3. Pentru n N funcia UrmatorPrim(n) d numrul prim imediat superior lui n.
4. Pentru polinomul P de gradul n cu coecieni reali dat i x R funcia
VALPOL(x, n, P) d valoarea polinomului P n punctul x.
5. Pentru k, n N, 0 k n, funcia C(n, k) calculeaz numrul combinrilor de
n obiecte luate cte k.
48 1. Bazele algoritmilor
6. Pentru vectorii X i Y cu n componente, funcia E(n, X, Y ) d valoarea 0 dac
X = Y, respectiv i dac i este cel mai mic indice pentru care x
i
< y
i
.
7. Cunoscnd mulimile A i B funcia INCLUS(A, B) veric dac mulimea A
este inclus n mulimea B;
8. Fie f o funcie de forma f : 1, 2, ..., m 1, 2, ..., n.
Denim T(f) egal cu 1 dac f este o funcie injectiv, egal cu 2 dac f este
surjectiv, egal cu 3 dac f este bijectiv, i 0 n caz contrar. Se d funcia f
prin perechile de elemente (x, f(x)) care denesc gracul su. S se calculeze
T(f).
9. Se d o relaie binar R prin gracul su. S se calculeze E(R) prin deniie
egal cu 0 dac R este o relaie de recuren i egal cu 1 n caz contrar.
10. irul Fibonacci este denit astfel: f
0
= f
1
= 1 i f
n
= f
n1
+ f
n2
, pentru
n > 1. Pentru n N dat calculai F(n) = f
n
.
11. Pentru n N dat calculai j(n), unde j este funcia lui Euler, deci j(n) este
numrul numerelor mai mici dect n i relativ prime cu n.
12. Pentru n N dat calculai P(n), unde P(n) este 0 dac numrul n este perfect
i 1 n caz contrar (un numr n este perfect dac este egal cu suma divizorilor
si mai mici dect el nsui. Exemplu: 6=1+2+3)
II. Scriei subalgoritmi pentru rezolvarea urmtoarelor probleme:
1. Cunoscnd mulimile A i B calculai C = A B;
2. Cunoscnd mulimile A i B calculai C = A B;
3. Dndu-se vectorul X cu n componente, tergei toate componentele care se
repet;
4. Dndu-se vectorul X cu n componente numere ntregi ordonate cresctor i
a Z inserai pe a n X astfel nct X s rmn ordonat cresctor;
5. Dndu-se dou polinoame calculai suma lor;
6. Dndu-se dou polinoame calculai produsul lor;
7. Dndu-se dou matrice calculai suma lor;
8. Dndu-se dou matrice ptrate de ordinul n calculai produsul lor;
1.7. Probleme propuse 49
9. Dndu-se dou numere A i B prin reprezentrile lor n baza p gsii suma lor
A+B prin reprezentarea ei n baza p;
10. Dndu-se numerele reale x
1
, x
2
, ..., x
n
, determinai secvena de termeni conse-
cutivi care are suma maxim.
11. Se dau p, q N i numrul A prin reprezentarea sa n baza p. Determinai
reprezentarea sa n baza q.
12. Se d n B, n 2. S se formeze matricea ptrat A de ordinul n ale crei
coloane scrise una dup alta constituie primii n
2
termeni ai irului
1,2,3,4,5,6,7,8,9,1,0,1,1,1,2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,2,0, ... obinut din scrierea
cifrelor semnicative ale numerelor naturale.
III. Proiectai prin metoda top-down algoritmi pentru rezolvarea urm-
toarelor probleme:
1. Se d un ir de numere naturale x
1
, x
2
, ..., x
n
. Spunem c dou numere naturale
sunt prietene dac scrierea unui numr (n baza 10) este obinut prin scrierea
cifrelor celuilalt n ordine invers (de exemplu 3678 i 8763). S se gseasc toate
perechile de numere consecutive prietene din irul dat i frecvenele cifrelor n
scrierea numerelor date.
2. Se d un ir de numere naturale x
1
, x
2
, ..., x
n
. S se gseasc toate subsirurile
de elemente consecutive de lungime maxima formate din numere prime i toate
numerele prime distincte ntlnite.
3. Se d o matrice ptrat A de ordinul n i numrul natural m > 0. Se cere s se
tipreasc matricele A, A
2
, ..., A
m
i suma lor.
4. Se d polinomul P cu coecieni ntregi, e prin monoamele sale, e prin grad
i coecieni. S se scrie un algoritm care determin rdcinile raionale ale
polinomului P.
5. Se dau numerele naturale n
1
i n
2
. Determinai mulimea numerelor prime
aate ntre n
1
i n
2
i mulimea perechilor de gemeni (numerele prime p i q se
numesc gemeni dac q p = 2).
6. Fiind date mai multe polinoame cu coecieni reali s se determine suma lor i
polinomul de grad maxim. Un polinom se d e prin monoamele sale, e prin
grad i coecieni.
50 1. Bazele algoritmilor
7. Se citesc mai multe iruri de numere naturale. Pentru ecare ir citit, tiprii cea
mai lung scar (secvena de termeni consecutivi strict cresctori) i depunei
aceast scar ntr-un ir (rezultat) R. La sfrit tiprii cea mai lung scar din
R. Citirea unui ir se termin la ntlnirea unui numr negativ, iar citirea se
oprete la ir de lungime 0 (deci fr nici un termen).
8. Se dau mai multe mulimi de numere ntregi pozitive. S se determine reuniunea
i intersecia acestor mulimi.
9. Se dau mai multe mulimi de numere naturale. Fie I(M) numrul mulimilor
diferite de M si care conin pe M. S se determine mulimea pentru care I(M)
este maxim.
10. O matrice rar A este o matrice n care majoritatea termenilor sunt nuli. O
astfel de matrice se poate reprezenta prin tripletele (linie, coloan, valoare)
corespunztoare valorilor nenule ale matricei; deci A(linie,coloan) = valoare.
Dndu-se mai multe matrice rare determinai suma lor.
11. Se dau mai multe numere naturale prin reprezentrile lor n baza p. Gsii suma
lor i maximul acestor numere (reprezentate n baza p i toate operaiile se fac
n baza p).
12. Se dau mai multe matrice cu coecieni ntregi. Se cere suma matricelor care
au determinantul nenul, matricele care au determinantul nul i matricea care
are determinantul maxim.
Capitolul 2
Complexitatea algoritmilor
2.1 Etapele rezolvrii unei probleme
Este cunoscut faptul c rezolvarea unei probleme presupune n principal trei etape:
1. Analiza problemei ;
2. Proiectarea soluiei ;
3. Implementarea i testarea soluiei n practic.
n funcie de gradul de generalitate a analizei efectuate, n a doua etap se ntlnesc
dou situaii: proiectarea unei soluii particulare, valabil doar pentru acea problem,
i proiectarea unei soluii generale, valabil pentru orice instaniere a acelei probleme,
soluia generalizat.
n timp ce soluia particular este valabil doar pentru o instan a problemei,
soluia general este independent de parametrii problemei i ofer o metod general
de rezolvare a problemei.
Astfel, soluionarea imediat a ecuaiei x
3
+ 1 = 0 este particular fa de
soluionarea ecuaiei generalizate ax
3
+bx
2
+c = 0.
2.2 Noiunea de algoritm i cea de program
Atunci cnd metoda general de rezolvare a unei probleme este prezentat precis, pe
pai ce se efectueaz ntr-o ordine bine precizat i care conduc n timp nit la soluia
oricrei instanieri a problemei, vorbim de algoritmul de rezolvare a problemei.
51
52 2. Complexitatea algoritmilor
De exemplu, algoritmul de determinare a unei soluii reale a ecuaiei polinomiale
P(x) = 0, cu o aproximare dat, prin metoda tangentei.
Avantajul major al proiectrii unui algoritm de soluionare a problemei este dat
de faptul c efortul de rezolvare poate transferat unei maini automate (calculator)
sub forma programului executabil ce implementeaz algoritmul general de soluionare.
Implementarea algoritmului general de soluionare a problemei ntr-un program
pe calculator permite o important economie prin faptul c efortul major de analiz i
proiectare a soluiei a fost efectuat o singur dat iar rezolvarea problemei se reduce
la efortul foarte redus de executare (rulare) a programului cu ajutorul calculatorului
pentru ecare instan diferit a problemei.
2.3 Modelul abstract al Mainii Turing. Teza
Turing-Church
Primul model teoretic riguros de main automat de calcul este Modelul mainii
abstracte Turing (1936). Acest model teoretic a stat la baza apariiei efective a
primei maini electronice de calcul, denumit mai trziu computer (calculator) dup
denumirea operatorului uman (tehnicianului) care era angajat s fac toate calculele
inginereti sau contabile ale unui proiect sau ale unei rme.
Puterea de rezolvare a unui calculator se reduce la puterea de calcul a mainii
Turing. Iar puterea de calcul a acestei maini abstracte riguroase este exprimat sub
forma Tezei Turing-Church: O main Turing poate face tot ceea ce poate face un
computer uman nzestrat cu creion, oricte foi de hrtie i reguli precise ( mecanice
sau automate ) de calcul.
Exist, pe lng aceast formulare iniial a lui Turing, o serie de alte formulri
echivalente ale acestei teze unanim acceptate de teoreticienii ce au pus bazele teoriei
informatice i a tiinei calculatoarelor (computer science). S observm c aceast
tez (propoziie acceptat fr demonstraie ca avnd valoarea logic de adevrat)
stabilete o echivalen perfect ntre puterea de calcul a unui computer uman i
puterea de calcul a unui computer main.
Echivalarea subneles (tacit) a noiunii teoretice vagi de algoritm cu noiunea
matematic riguroas de Main Turing a nsemnat acceptarea unanim a Tezei
Turing-Church de ctre iniiatorii informaticii. n consecin, studiul ecienei unui
algoritm n soluionarea unei probleme revine n studiul ecienei n funcionare a
mainii Turing i implicit a ecienei n funcionare a programului ce implementeaz
acel algoritm de rezolvare.
Aceasta este consecina faptului c, n accepiunea original, algoritmul de
2.4. Analiza, Proiectarea i Implementarea algoritmilor 53
soluionare a unei probleme este destinat unui computer uman, dar puterea de calcul
a acestuia este aceeai cu puterea de calcul a unei maini Turing = computer main
care este pus n micare printr-un program executabil.
2.4 Analiza, proiectarea i implementarea algorit-
milor i complexitatea algoritmilor
Relund ideea iniial, n rezolvarea automat a unei probleme (adic rezolvarea cu
ajutorul calculatorului a oricrei instane diferite problemei) se trece prin cele trei
etape: Analiza teoretic a problemei, Proiectarea algoritmului de soluionare i Im-
plementarea algoritmului ntr-un program executabil pe calculator.
n timp ce n prima etap analiza problemei - rezultatul cheie, pe care se concen-
treaz preponderent efortul de analiz, este demonstrarea corectitudinii soluiei, n a
doua etap proiectarea algoritmului de soluionare - cuvntul cheie este eciena de
rezolvare. Studiul cu un pronunat caracter teoretic coninut n aceast a doua etap
i propune s prevad eciena n funcionare (necesarul de timp i spaiu calcula-
tor) a programului executabil ce va implementa algoritmul, eventual prin compararea
teoretic a algoritmilor de soluionare diferii [Aho, 1974].
De exemplu, n cazul problemei sortrii unui ir de n chei prin comparaii se poate
estima teoretic comparativ c algoritmul de sortare QuickSort este printre cele mai
eciente soluii.
Disciplina informaticii care se ocup cu studiul teoretic al ecienei algoritmilor
este numit Complexitatea algoritmilor.
2.5 Operaia de baz, cheia studiului complexitii
La baza studierii complexitii unui algoritm st detectarea n descrierea algoritmului
a operaiei sau a operaiilor de baz, acea operaie (acele operaii) aat (aate) n cel
mai interior corp de ciclu repetitiv i a crei (a cror) contorizare permite estimarea n
avans, nainte de lansarea n execuie, a timpului de execuie a programului executabil
corespunztor.
n majoritatea cazurilor exist o legtur foarte strns ntre operaia de baz (cea
mai repetat operaie) i operaia care este dedus n etapa de analiz a problemei
ca ind operaia inevitabil pentru rezolvarea problemei.
De exemplu, n cazul problemei sortrii unui ir de n chei prin comparaii este
limpede c operaia de comparare a mrimii cheilor este operaia inevitabil i de
asemenea ea va i operaia de baz a crei contorizare va permite estimarea, nainte
54 2. Complexitatea algoritmilor
de execuie, a duratei de funcionare a programului ce implementeaz algoritmul de
sortare respectiv.
2.6 Clase de algoritmi
n aceast situaie, toi algoritmii diferii care soluioneaz aceeai problem i care
se bazeaz pe aceeai operaie de baz (inevitabil) formeaz clasa algoritmilor de
soluionare a problemei. De obicei, numele clasei va dat chiar de numele acelei
operaii de baz ce este coninut de ecare algoritm al clasei n mod inevitabil.
De exemplu, n cazul problemei sortrii unui ir de n chei prin comparaii, algo-
ritmii diferii ce soluioneaz problema sunt grupai n clasa algoritmilor de sortare
prin comparaii, spre deosebire de clasa algoritmilor de sortare prin distribuire ce
soluioneaz aceeai problem bazndu-se ns pe alt operaie de baz: distribuirea
cheilor de sortat.
2.7 Eciena algoritmilor
Compararea ecienei a doi algoritmi diferii ce soluioneaz aceeai problem se face
prin determinarea teoretic a numrului de repetiii a operaiei de baz n ecare
algoritm i compararea celor dou valori. n nal, rezultatul comparrii va permite
estimarea comparativ a duratei de funcionare a programelor i alegerea celui mai
bun.
Compararea ecienei a doi algoritmi, din punct de vedere practic, se face prin
compararea timpilor medii de execuie a celor dou programe ce i implementeaz.
Aceast metod pragmatic are dezavantajul c necesit rularea programelor care, n
anumite situaii, poate dura un timp surprinztor de mare.
2.8 Funciile de complexitate
Numrul de repetiii al operaiei de baz se exprim matematic printr-o funcie de
complexitate individual asociat algoritmului, funcie ce depinde n mod inevitabil
de dimensiunea (mrimea) vectorului datelor de intrare.
De exemplu, n cazul algoritmului de determinare a maximului dintr-un ir de n
elemente prin comparaii, este evident c numrul de comparaii efectuat de orice
algoritm de maxim va o funcie de n. Iat descrierea n Pseudocod a algoritmului
[Liv, 1986]:
2.9. Apartenena la o clas de complexitate 55
Citete n, a
1
, a
2
, . . . , a
n
; Dup cum se observ vectorul de intrare (irul a) are
dimensiunea n.
Max := a
1
;
Pentru i := 2 pn la n execut Este evident c operaia de baz comparaia
< se execut de
Dac Max < a
i
atunci Max := a
i
; n 1 ori, adic pentru valorile contorului i
cuprinse ntre 2 i n.
Scrie Max; Deci, funcia care descrie numrul operaiilor de baz este: f(n) = n1
n studiul complexitii algoritmilor, pentru a permite realizarea comparailor
necesare pentru clasicarea algoritmului din punct de vedere al ecienei, dimensiunea
vectorului de intrare este mpins spre innit.
Compararea complexitii algoritmilor dintr-o clas de algoritmi cere n mod ine-
vitabil gruparea funciilor de complexitate n clase de funcii de complexitate i studiul
comportamentului asimptotic al acestora (cnd n dimensiunea vectorului de intrare
tinde ctre innit).
2.9 Apartenena la o clas de complexitate
Complexitatea unui algoritm se poate exprima prin precizarea clasei de apartenen a
funciei de complexitate a respectivului algoritm. Notaiile clasice care exprim felul
apartenenei funciei de complexitate f(n) a unui algoritm la diverse clase de funcii
sunt , i O.
n aceast introducere snt prezentate noiuni de baz folosite n capitolele urm-
toare ale lucrrii.
Deniia 2.9.1. Un algoritm este un set de instruciuni care trebuie executate pentru
a se obine un rspuns la o problem dat.
Un algoritm are urmtoarele proprieti [Knu, 1976], [Bur, 1998]:
nitudine: trebuie s se termine ntotdeauna dup un numr nit de pai (in-
struciuni);
determinism: ecare pas trebuie s e exact precizat, n mod riguros i neam-
biguu;
generalitate: trebuie s rezolve problema pentru orice date de intrare din dome-
niul precizat;
efectivitate: ecare instruciune trebuie s e exact i de durat nit.
56 2. Complexitatea algoritmilor
Ultima proprietate trebuie nuanat, avnd n vedere faptul c memoria oricrui
calculator este limitat. Nu ntotdeauna operaiile aritmetice se efectueaz exact,
n unele cazuri obinndu-se o aproximare a rezultatelor. Exist i soluii propuse
pentru respectarea acestei proprieti, care presupun implementarea software a oper-
aiilor elementare cu numere ntregi [For, 1993], dar acestea duc la scderea vitezei de
prelucrare. De aceea, abordri recente iau n considerare modelul bazat pe aritmetica
n virgul mobil, implementat pe toate calculatoarele actuale [She, 1997].
Avnd un algoritm care rezolv o problem dat, urmeaz s determinm resursele
acestuia [Liv, 1986]. Concret, de ct memorie i timp avem nevoie ca s obinem
soluia problemei? n acest scop facem urmtoarele simplicri: ecare operaie ele-
mentar a algoritmului se execut ntr-o unitate de timp, informaiile despre un obiect
elementar se memoreaz ntr-o locaie de memorie.
Fie f : N N o funcie care indic relaia dintre numrul de valori (date de
intrare) prelucrate de un algoritm, i numrul de operaii elementare efectuate de
acesta pentru obinerea rezultatelor. Funcia f poate avea o expresie analitic destul
de complicat, de aceea considerm nc o funcie g : N N cu o expresie analitic
simplicat.
Deniia 2.9.2. Funcia f are ordinul de mrime cel mult g(n), notaie: f O(g(n)),
dac i numai dac exist valori c > 0 i n
0
N astfel nct pentru orice n > n
0
s
avem f(n) cg(n).
O(g) = h : N N [ c > 0, n
0
N a. v > n
0
, h(n) cg(n). (2.1)
Deniia 2.9.3. Funcia f are ordinul de mrime cel puin g(n), notaie: f
(g(n)), dac i numai dac exist valori c > 0 i n
0
N astfel nct pentru orice
n > n
0
s avem f(n) cg(n).
(g) = h : N N [ c > 0, n
0
N a. v > n
0
, h(n) cg(n). (2.2)
Deniia 2.9.4. Funcia f are ordinul de mrime g(n), notaie: f (g(n)), dac i
numai dac exist valori c
1
, c
2
> 0 i n
0
N astfel nct pentru orice n > n
0
s avem
c
1
g(n) f(n) c
2
g(n).
(g) = h : N N [ c
1
, c
2
> 0, n
0
N a. v > n
0
, c
1
g(n) h(n) c
2
g(n).
(2.3)
Prezentm dou rezultate remarcabile care vor folosite foarte frecvent pe par-
cursul lucrrii [Knu, 1976]:
2.9. Apartenena la o clas de complexitate 57
(1) Se d un ir de n valori dintr-un domeniu pe care este denit o relaie de
ordine total. Cel mai ecient algoritm de ordonare a irului dat, care se bazeaz pe
comparaii, are complexitate de ordin (nlog n).
(2) Se d un ir de n valori ordonate. Cutarea unei valori (localizarea poziiei
acesteia sau obinerea unui rspuns negativ) n irul dat necesit un timp de ordin
O(log n).
O categorie special de probleme, numite NP-complete, se caracterizeaz prin
urmtoarele:
nu se cunosc algoritmi ecieni (de complexitate polinomial), se cunosc n
schimb algoritmi de complexitate exponenial pentru rezolvarea acestora;
problem NP-complet este polinomial transformabil ntr-o alt problem tot
NP-complet: dac se rezolv o problem A, soluia unei alte probleme B se
poate obine printr-o transformare n timp polinomial din soluia problemei A.
Cea mai general problem NP-complet este problema satisabilitii: ind dat
o expresie logic n forma normal conjunctiv cu n variabile, s se determine dac
pot atribuite valori logice variabilelor astfel nct expresia s e adevrat [Coo,
1970].
Complexitatea medie. Considerm un algoritm care proceseaz n valori date
la intrare. Pentru o anumit conguraie a valorilor, probabilitatea conguraiei ind
p
i
, sunt necesare f
i
(n) operaii. Complexitatea medie a algoritmului este o sum
ponderat:

i
p
i
f
i
(n).
Exemplul 2.9.1. Algoritmul Quick-sort necesit un timp de ordin O(nlog n) n ma-
joritatea cazurilor pentru a ordona un ir de n valori. Exist ns cteva conguraii
(foarte puine) care au nevoie de un timp de ordin O(n
2
) pentru a procesate. Com-
plexitatea medie a acestui algoritm este de ordin O(nlog n) [Knu, 1976].
ntr-un mod similar se poate deni noiunea de complexitate pentru necesarul de
memorie. Aceasta arat ct memorie este necesar pentru rezultatele intermediare
i cele de ieire.
Deniiile date mai sus asigur o estimare a ecienei unui algoritm independent
de o implementare practic a acestuia folosind un anumit limbaj de programare,
urmrindu-se ascunderea factorului multiplicativ. Totui acest factor nu poate
ntotdeauna ignorat, deoarece exist probleme care admit mai muli algoritmi cu
acelai ordin de complexitate, i atunci trebuie s se efectueze o ranare a studiului
complexitii. Rezultate recente arat c aceast constant poate inuena eciena
58 2. Complexitatea algoritmilor
unor implementri, de aceea abordrile clasice ale acestui subiect trebuie privite cu
rezerve.
Unele probleme de optimizare se rezolv cu ajutorul unor algoritmi de complexitate
mare, exemplu: probleme NP-complete sau de complexitate O(n
d
). n asemenea
situaii ne mulumim cu soluii aproximative obinute cu ajutorul unor algoritmi
euristici, mult mai ecieni i de cele mai multe ori mai simpli.
O categorie special, frecvent ntlnit mai ales n probleme de geometrie, este
aceea a algoritmilor incrementali. Un algoritm din aceast categorie proceseaz val-
orile de intrare una cte una, la ecare pas obinndu-se o soluie parial pentru
datele deja procesate.
Dac algoritmul de determinare a maximului din n chei prin comparaii efectueaz
un numr liniar de comparaii (adic proporional cu n) atunci se spune c el este
un algoritm (n) (adic are funcia de complexitate din (n) = mulimea funciilor
lineare de forma c n), iar dac efectueaz cel puin, respectiv cel mult, tot attea
comparaii (adic proporional cu n) se spune c algoritmul este (n), respectiv O(n).
Clasele de funcii de complexitate, i implicit clasele de complexitate a algoritmilor,
cele mai des ntlnite, n ordine cresctoare a complexitii sunt: (lnn) - clasa
algoritmilor cu complexitate logaritmic(timpul de execuie va egal cu c lnn), (n)
- liniar (timpul de execuie va egal cu c n), (n lnn) - liniar-logaritmic (timpul
de execuie va egal cu c n lnn), (P(n)) - polinomial (timpul de execuie va
egal cu c P(n)), (e
x
) - exponenial (timpul de execuie va egal cu c Exp(n)) sau
(n!) - factorial (timpul de execuie va egal cu c n!). Peste tot c este o constant
de proporionalitate care depinde de calculatorul pe care se ruleaz programele.
Iat cte un exemplu de algoritm din literatura de specialitate, corespunztor
ecrei clase: algoritmul de cutare binar BinarynSearch - (log n), algoritmul de
determinare a maximului Max - (n) , algoritmul de sortare prin comparaii Quick-
Sort - n log n), algoritmul comun de nmulire a matricelor - (n
3
), algoritmul de
colorare optim cu k culori a unui graf cu n noduri prin ncercri repetate - (k
n
),
respectiv, algoritmul de generare a permutrilor - (n!), toi algoritmii avnd vectorul
de intrare cu n elemente (de dimensiune n).
2.10 Limita inferioar sau efortul minimal. Algoritm
optimal
Atunci cnd ntr-o clas de algoritmi, toi bazai pe aceeai operaie de baz, se poate
stabili o limit inferioar a numrului de operaii de baz inevitabile ce trebuiesc efec-
tuate pentru soluionarea problemei, putem vorbi despre efortul minimal de rezolvare
2.11. Complexitatea algoritmilor i dicultatea problemelor 59
i despre algoritmul optimal de rezolvare a problemei respective.
Algoritmul optimal este acel algoritm care efectueaz cel mai mic numr de operaii
de baz dintre toi algoritmii clasei sale, cunoscui sau neinventai nc (o clas de
algoritmi prin criteriul su de apartenen - prezena operaiei de baz inevitabile -
include obligatoriu n acea clas toi algoritmii ce rezolv problema bazndu-se pe
operaia respectiv, chiar i algoritmii nedescoperii nc !).
De exemplu, n clasa algoritmilor de sortare prin comparaii se nelege c este
aparintor orice algoritm de sortare bazat pe comparaii cunoscut sau necunoscut
nc. n plus, limita inferioar a numrului de comparaii necesar pentru sortarea
listei de n elemente (efortul minimal ) prin comparaii este demonstrat riguros ca
ind log
2
n! dar un algoritm optimal care s efectueze exact attea operaii de baz
(comparaii) nu se cunoate.
n clasa algoritmilor de determinare a maximului prin comparaii, algoritmul clasic
de determinare a maximului este un algoritm optimal ntruct el efectueaz un numr
minimal de comparaii inevitabile: n 1.
2.11 Complexitatea algoritmilor i dicultatea prob-
lemelor
Din perspectiva rezolvrii problemelor cu ajutorul calculatorului putem studia i com-
para dicultatea problemelor studiind i comparnd complexitatea algoritmilor opti-
mali de soluionare a acestora.
Astfel, problema sortrii prin comparaii cere un efort minimal liniar-logaritmic.
Ea nu este totui o problem de efort liniar-logaritmic((n log n)) ntruct ea poate
soluionat cu efort liniar((n) operaii) atunci cnd cheile de sortare pot dis-
tribuite folosind un algoritm de sortare prin distribuire.
2.12 Complexitatea de timp
Msurarea n practic a duratei de execuie (adic a complexitii de timp) a im-
plementrii algoritmilor a condus la urmtoarea concluzie categoric: singurii algo-
ritmi ce soluioneaz n mod ecient o problem oarecare sunt acei algoritmi care
au complexitatea polinomial (sau mai mic dect exponenial). O astfel de soluie
se numete soluie rezonabil, fa de cealalt situaie cu soluie nerezonabil avnd
o complexitate de timp exponenial sau factorial (total inecient ca durat de
execuie).
60 2. Complexitatea algoritmilor
De exemplu, dac pentru colorarea unui graf cu n vrfuri cu doar trei culori, se
ncearc toate cele 3
n
variante de colorare (printr-un algoritm de tip backtracking),
timpul necesar unui program pentru epuizarea tuturor cazurilor, n cazul n care
n = 100, este direct proporional cu uriaa valoare de 3
100
= 387420489
10
ceea ce face
acel program cu totul inutilizabil (chiar dac am presupune c o instruciune s-ar
executa ntr-o pico-secund = 10
12
s).
2.13 Probleme rezonabile i probleme nerezonabile.
Clasa problemelor P-polinomiale
Dup efortul de rezolvare necesar, reductibil n ultim instan la durat de execuie a
programului, problemele se pot mpri n probleme rezonabile i nerezonabile. innd
cont de cele de mai sus, problemele rezonabile sunt problemele de dicultate polino-
mial i ele sunt grupate n clasa problemelor P (Clasa problemelor Polinomiale).
Pentru ecare problem din aceast clas se cunoate un algoritm de soluionare cu
complexitate polinomial, adic programul ce implementeaz acest algoritm are o du-
rat de execuie proporional cu o funcie polinomial de n, unde n este dimensiunea
datelor de intrare.
Exist cu siguran probleme ce nu fac parte din aceast clas P: de exemplu,
problema generrii tuturor celor n! permutri ale unui ir de n elemente distincte,
care are inevitabil dicultatea (durata de execuie) factorial n!.
2.14 Probleme de decizie i probleme de optimizare
n ncercarea de a studia i clasica dicultatea problemelor ne-polinomiale (nerezon-
abile ca durat de rezolvare cu ajutorul calculatorului) ele au fost grupate n dou
categorii: probleme n varianta de decizie, n care se cere doar s se decid prin DA
sau NU dac exist pentru problema respectiv o soluie bine precizat, i probleme n
varianta de optimizare, n care se cere determinarea soluiei optime pentru problema
respectiv.
De exemplu, problema colorrii grafului n varianta de decizie cere s se decid
dac un graf poate colorat cu k culori, unde k este precizat dinainte. Aceeai
problem, n varianta de optimizare, cere s se determine X - numrul minim de
culori necesar (numrul cromatic) pentru colorarea unui graf (astfel nct oricare
dou vrfuri adiacente s e colorate diferit), X ind evident un numr ce nu poate
precizat dinainte.
2.15. Clasa problemelor NP (non - deterministic polinomiale) 61
2.15 Clasa problemelor NP (non - deterministic poli-
nomiale)
Exist o clas larg de probleme de decizie cu extrem de numeroase aplicaii practice
numit clasa problemelor NP(non-deterministic polinomiale). Aceast clas include
pe lng toate problemele de decizie din P i o mulime foarte mare de probleme de
decizie (toate inspirate din practic) crora nu li se cunoate o soluie polinomial.
Pentru a putea explica de ce sunt numite NP (non-deterministice), este necesar s
revenim la echivalarea unanim acceptat de teoreticienii informaticii ntre noiunea
de algoritm i noiunea de main Turing. Astfel, pentru ecare din problemele NP
se cunoate o soluie sub forma unei maini Turing nedeterministice(!) (care la o
tranziie de stare poate trece dintr-o stare ntr-una din oricare alte k stri posibile,
fr a se putea preciza exact n care) care se oprete furniznd soluia dup un numr
polinomial de pai.
n termenii algoritmici, aceeai non-determinarea este exprimat astfel: o prob-
lem NP este o problem ce are un algoritm de soluionare care decide n timp poli-
nomial dac o soluie propus (prin "ghicire" sau "inventare" ) este sau nu valid.
n aceti termeni, nedeterminarea const mai exact n faptul c sub-algoritmul
de ghicire sau inventare de soluii, din cauz c nu poate parcurge ntreg spaiul
soluiilor posibile pentru c nu ar mai rmne un algoritm polinomial, nu ofer nici
o garanie c gsete sau c se apropie mcar n vreun fel de soluia problemei prin
simpl ghicire.
2.16 Reducia polinomial a problemelor
n intenia de a compara dicultatea problemelor de decizie ntre ele s-a sesizat c
dac exist un algoritm de transformare T a datelor de intrare D

ale unei probleme


de decizie P

astfel nct noile date de intrare D = T(D

) s se potriveasc ca date
de intrare unei probleme de decizie P, ce are ca soluie un algoritm de soluionare
cunoscut A, atunci un algoritm de soluionare A

a problemei P

se obine imediat
prin compunerea algoritmului A cu transformarea T astfel nct A

= A T.
Dac complexitatea algoritmului de transformare T este rezonabil (polinomial)
atunci nseamn c complexitatea algoritmului A

obinut prin compunere este tot


att de rezonabil cu cea a algoritmului A care este cunoscut (adic, dac A are
complexitate polinomial i A

va avea tot o complexitatea polinomial obinut prin


compunerea celor dou funcii de complexitate polinomiale corespunztoare lui A
i T). n acest caz, cnd algoritmul T de transformare a intrrii unei probleme n
62 2. Complexitatea algoritmilor
intrarea alteia este de complexitate polinomial, atunci ntreag aceast metod ce
transform soluionarea problemei P

n soluionarea problemei P cunoscut deja,


se numete reducie polinomial iar cele dou probleme se spune c se reduc una la
cealalt: P P.
De exemplu, se poate arta c Problema Orarului (unui institut de nvmnt)
este reductibil la Problema Colorrii Grafului prin faptul c sub-algoritmul de trans-
formare a orelor de predare/zile/clase/profesori n nodurile unui graf este liniar iar
aezarea orelor pe orar este echivalent cu colorarea grafului obinut prin aceast
transformare liniar.
Atunci cnd dou probleme P i P

se reduc polinomial reciproc una la cealalt,


adic P P i P P, se spune c cele dou probleme sunt echivalente.
Desigur, innd cont de cele zise mai sus, se poate arta c Problema Orarului i
Problema Colorrii Grafului sunt echivalente.
2.17 Teorema lui Cook. Probleme NP-Complete
Bazndu-se pe Teza Turing-Church i folosind cteva elemente de calcul logic propo-
ziional, n 1971 Cook a demonstrat o teorem fundamental pentru domeniul com-
plexitii algoritmilor. Teorema lui Cook arm c: Toate problemele NP sunt
reductibile polinomial la Problema FNC, deci problema FNC este o prob-
lem NP-complet.
Problema FNC (Problema Formei Normale Conjuctive) cere s se decid dac
este posibil s existe o alegere de valori logice Adevrat sau Fals pentru n variabile
logice x
1
, x
2
, . . . , x
n
ce apar ntr-o form normal conjunctiv (format dintr-un ir
de clauze conjugate, ecare clauz ind obinut doar prin compunerea sau logic
a variabilelor x
i
sau negaiei lor |x
i
) astfel nct valoarea logic a propoziiei logice
nale s e Adevrat.
De exemplu, e x, y, z cele trei variabile logice, o form normal conjuctiv posibil
cu trei clauze conjugate este: (x y) (x|y|z) (|x z) ce admite ca soluie
x=Adevrat, y=Adevrat sau Fals i z=Adevrat.
2.18 Clasa problemelor NP-Complete
Dup descoperirea i demonstrarea existenei primei probleme NP-complete a ur-
mat demonstrarea NP-completitudinii, prin echivalarea cu problema FNC, a unei
serii ntregi de probleme clasice din informatic i cunoscute ca ind probleme ex-
trem de dicil de soluionat ecient n timp: Problema Colorrii Grafului, Problema
2.19. Marea ntrebare a Complexitii algoritmilor 63
Partiionrii Sumei, Problema Comis-Voiajorului, Problema Rucsacului, Problema
Planicrii Sarcinilor cu Penalizri, etc [Cri, 1993].
S-a obinut astfel clasa problemelor NP-complete ce au neobinuita proprietate c
prin soluionarea n timp polinomial doar a uneia dintre ele se va obine automat n
consecin soluia polinomial pentru toate celelalte.
Din pcate, pentru nici una din sutele de probleme NP-complete inventariate pn
acum nu se cunoate o soluie polinomial (rezonabil n timp de execuie). ns nu
s-a putut demonstra c vreuna dintre ele nu poate admite o soluie polinomial.
2.19 Marea ntrebare a Complexitii algoritmilor
Aceasta este Marea ntrebare a complexitii algoritmilor dar i a informaticii: P =
NP? Snt problemele NP reductibile la cele din P? Pot exista soluii polinomiale
pentru problemele NP?
Rspunsul la Marea ntrebare este de importan capital pentru majoritatea
domeniilor practice n care calculatorul are un rol tot mai important (strategic, am
putea zice): reele de transport i reele de comunicaii, astronautic i aeronautic,
domeniile militare i a serviciilor de informaii, proiectarea automat, urmrirea au-
tomat i controlul proceselor industriale, etc. Un rspuns armativ, P=NP, ar avea
ca i consecin imediat posibilitatea introducerii calculatorului n deplin siguran
n poziiile de decizie i control automat a proceselor cheie a ecruia din domeni-
ile amintite, datorit capacitii algoritmilor implementai de a lua decizii optime n
timp real (rezonabil) n orice situaie.
Atunci, actualul nume: era informatizrii, prematur acordat perioadei ultimilor
ani, s-ar potrivii cu adevrat ntru-totul, iar noiunile de pilot automat sau robot ar
face parte din viaa cotidian a ecruia. Merit aici s atragem atenia asupra puterii
extraordinare pe care o vor dobndi n acea situaie cei ce supervizeaz i programeaz
calculatoarele aate n puncte strategice de decizie, putere ce fr exagerare ar putea
numit planetar, i de aceea considerm c:
din pcate ansele de a aa cu toii despre existena rspunsului armativ la Marea
ntrebare, nainte ca consecinele strategice ale acestuia s fost deja puse n practic
la scar planetar, sunt minime.
Pentru a rspunde ns negativ la Marea ntrebare este sucient s se demonstreze
riguros c una din problemele NP-complete are o complexitate exponenial, deci cu
siguran nu admite o soluie cu timp de execuie polinomial. Sau, altfel spus, ar
sucient s se arate riguros c ntr-o anumit problem NP-complet, numrul de
operaii de baz inevitabile nu poate mai mic dect exponenial.
64 2. Complexitatea algoritmilor
n situaia unui rspuns negativ la Marea ntrebare, toate punctele de decizie n
timp real vor ocupate ca i pn acum de operatori umani ce nu trebuie i nu pot
privii ca computere umane, ei comportndu-se uneori omenete, deci ntr-un mod
nedeterminist. S nu uitm c avem cu toii experiena momentelor cruciale din viaa
personal ce au cerut stringent luarea unei decizii i n majoritatea cazurilor decizia
luat de noi n-a fost una de tip raional, algoritmic sau dup o reet anume, ci
soluia aleas a avut o component subiectiv intuitiv sau chiar ilogic.
2.20 Algoritmi aproximativi
ntruct nu sunt nc semne clare c se va putea gsi n viitorul imediat rspunsul
la Marea ntrebare, dei se fac eforturi mari n aceast direcie, disciplina Complexi-
tatea algoritmilor s-a mbogit prin introducerea unui capitol consistent: Proiectarea
i studiul complexitii algoritmilor aproximativi. n primul rnd trebuie precizat
c nu este necesar proiectarea unor astfel de algoritmi dect n cazul problemelor
crora nu li se cunoate o soluie rezonabil (alta dect exponenial). Prin algoritm
aproximativ se nelege un algoritm de complexitate polinomial (o soluie rezonabil,
deci) care ns nu este capabil s determine soluia optim a problemei ci doar una
aproximativ. Studiul complexitii algoritmilor aproximativi se ocup cu estimarea
teoretic a gradului de aproximare pe care soluia algoritmului aproximativ o ofer,
deci implicit studiul ecienei acestuia. Este evident c, atunci cnd soluia aproxi-
mativ este foarte apropiat de soluia optim iar timpul de obinere al ei este unul
polinomial i nu exponenial, este avantajoas folosirea n practic a unui algoritm
aproximativ performant. Desigur, soluiile oferite de algoritmii aproximativi, chiar
dac se apropie de soluia optim a problemei, nu ofer ns nici o informaie n plus
despre soluia optim, aceasta rmnnd n continuare nedeterminat.
De exemplu, n cazul Problemei Colorrii Grafului [Tom, 1972], soluia optim
cere determinarea numrului cromatic, adic a numrului minim de culori necesare
pentru colorarea nodurilor grafului astfel nct oricare dou vrfuri adiacente s e
colorate diferit.
Un exemplu de algoritm aproximativ de colorare a grafului ar urmtorul: e
c
1
, c
2
, . . . , c
k
, . . . irul culorilor; parcurgnd ntr-o anumit ordine mulimea celor n
vrfuri ale grafului v
1
, v
2
, . . . , v
n
se coloreaz ecare vrf cu culoarea de indice mini-
mal care i este permis (innd cont de culorile nodurilor adiacente lui). Parcurgerea
celor n vrfuri precum i selectarea culorii de indice minim necesit un timp poli-
nomial, deci acest algoritm aproximativ este ecient n practic. Ceea ce este mai
dicil este estimarea gradului de aproximare a soluiei optime. Aceasta se face prin
2.21. Probleme insolvabile algoritmic 65
calcularea mediei rapoartelor ntre numrul de culori obinut cu ajutorul acestui al-
goritm aproximativ i numrul cromatic (care va trebui aat apelnd la un algoritm
exponenial, gen backtracking). Eciena acestui algoritm aproximativ este dat de
msura n care valoarea medie a raportului se apropie de valoarea 1.
2.21 Probleme insolvabile algoritmic
Chiar dac nu se cunoate nc rspunsul la Marea ntrebare, se cunoate n schimb
rspunsul la o alt ntrebare important:
exist probleme ce nu pot soluionate cu ajutorul calculatorului ?
Rspunsul este armativ i el a fost pentru prima dat armat n 1936 chiar de
Alan Turing, printele calculatoarelor actuale. Eforturile principale ale lui Turing la
acea vreme erau concentrate tocmai pentru cutarea rspunsului la aceast ntrebare.
Lipsa de rigurozitate a noiunilor: problem, soluie i calculator l-au obligat pe
Turing s imagineze modelul matematic riguros al mainii Turing i s formuleze
Teza sa ce permite echivalarea mainii Turing cu noiunea vag de algoritm, noiune
care ine locul noiunii i mai vagi de soluie general a unei probleme.
Enunul simplicat al Problemei Stopului care l-a condus pe Turing la rspunsul
ntrebrii exist probleme insolvabile algoritmic? n mod armativ (printr-un exemplu
concret de problem) este urmtorul:
Exist vreo metod general i nit care s decid dac un algoritm (sau o proce-
dur automat) ofer rspuns n timp nit pentru un set de date de intrare oarecare?
Ea este foarte asemntoare cu o alt problem insolvabil algoritmic, Problema
a zecea a lui Hilbert:
exist o metod general care s decid n timp nit dac o ecuaie diofantic
oarecare are sau nu soluie n numere ntregi ?
Ideea cheie care st la baza demonstraiei riguroase a insolvabilitii acestor prob-
leme nu este nou, ci ea a aprut pentru ntia oar n demonstraia teoremelor de
incompletitudine ale matematicii ale lui Gdel de la nceputul anilor 30. Aceast
idee este inspirat din faimosul paradox antic al mincinosului. Astfel, propoziiile de
genul Eu sunt mincinos sau Eu spun n ecare moment o minciun au un coninut
paradoxal. n analizarea coninutului logic al acestor propoziii, care din punct de
vedere semantic sunt de fapt nite negaii, se ajunge rapid la paradoxul semantic de
negare a negaiei i, n consecin, nu li se poate determina valoare logic de adevrat
sau fals. Adic, este inacceptabil ca ele s e adevrate, i este inacceptabil ca ele s
e false! Godel i Turing au artat n mod asemntor c presupunnd, prin reducere
la absurd, c matematica este complet respectiv c problema stopului este solvabil
66 2. Complexitatea algoritmilor
se va ajunge inevitabil la propoziii paradoxale din punct de vedere matematic riguros
al coninutului logic.
2.22 Complexitatea algoritmilor, calculatorul i vi-
itorul
De la Gdel i Turing ncoace (anii 30) au aprut o mulime de alte probleme insolva-
bile algoritmic (ecare surprinznd oarecum prin simplicitatea enunului) i despre
care putem spune c vor rmne s e rezolvate exclusiv prin puterea minii umane
(fr ajutorul mainilor automate actuale), cel puin ct vreme va pstrat modelul
abstract ce st la baza calculatoarelor actuale. Momentan aceste probleme au o
dicultate ce depete puterea noastr i nu li se pot ntrezrii soluii. Vor aceste
probleme soluionate vreodat ? Nu putem arma, nici c vor , nici c nu vor putea
soluionate, dar c sunt cele mai complexe i mai dicile probleme ce au aprut n
matematic i informatic putem arma cu siguran.
Capitolul 3
Pogramare n limbajul PASCAL
Pentru a putea utiliza algoritmii la rezolvarea problemelor, este necesar ca ei s e
"implementai" ntr-un limbaj "neles" de calculator, iar acesta s execute aciunile
cerute de algoritm. Iar pentru a nva corect programarea este necesar s se neleag
ntreaga activitate de programare. n plus, testarea algoritmilor implementai se poate
face doar prin traducerea acestora ntr-un limbaj de programare. n acest scop vom
prezenta un minim de cunotine despre limbajul Pascal, suciente ns pentru a scrie
programe pentru a rezolva o varietate mare de probleme de matematic [Boi, 1992].
3.1 Mediul de programare Turbo Pascal
Mediul de programare Turbo Pascal este un ansamblu de programe conceput pentru
programatorii care utilizeaz limbajul Pascal. Mediul Turbo Pascal permite editarea
(introducerea i corectarea) programelor Pascal, compilarea programului surs intro-
dus, execuia acestuia, dac el este corect sintactic i lexical. Programarea n limbajul
Pascal este mult uurat de acest mediu de programare interactiv cu ajutorul cruia
programatorul poate corecta uor erorile de compilare semnalate direct pe ecran n
programul surs unde a fost indicat eroarea (prima eroare dac sunt mai multe).
Dup corectarea erorii programul se poate compila din nou pn cnd se ajunge la
o variant corect. n continuare se poate testa programul introdus prin execuia
acestuia. Toate aceste etape prezentate anterior (editare, compilare, execuie, pre-
cum i altele) se pot parcurge uor din acest mediu, fr a mai apela la alte programe
utilitare. Odat apelat mediul Turbo Pascal, putem efectua toate operaiile necesare
parcurgerii etapelor programului Pascal fr a prsi mediul. Prsirea mediului se
va face doar la sfrit cnd programul este terminat.
67
68 3. Pogramare n limbajul PASCAL
Mediul de programare ofer o interfa prietenoas printr-un sistem de meniuri
i opiuni ce permit editarea ierelor surs Pascal, compilarea acestora, execuia
programelor obinute, depanarea lor i multe altele.
Pornirea mediului de programare Turbo Pascal se face prin comanda
Turbo<Enter> ntr-un mediu MS-DOS, sau prin accesarea corespunztoare a unei
icoane care corespunde mediului de programare n cazul mediului Windows. Lansarea
n execuie a mediului de programare Turbo Pascal este semnalat de deschiderea unei
fereastre de editare care permite editarea textelor surs Pascal (programele scrise n
limbajul Pascal). n partea de superioar a ferestrei este aat meniul principal iar n
partea inferioar sunt aate cteva comenzi importante ce se pot efectua direct fr
a apela sistemul de meniuri.
Pentru a accesa un ier ce conine cod surs Pascal vom putea tasta direct F3
sau putem accesa ierul prin intermediul meniului principal (F10 - submeniul File
opiunea Open), dup care se va tasta numele ierului (de exemplu Test<Enter>).
Dup aceasta, ierul cu numele specicat i extensia implicit PAS va des-
chis, iar fereastra de editare este pregtit pentru editarea programului (exemplu:
Test.Pas).
Programul se va introduce rnd cu rnd, ecare rnd ind terminat cu <Enter>.
Dup ce programul a fost introdus se poate compila pentru a depista eventualele erori
sintactice i lexicale. Aceasta se poate realiza e direct, prin tastarea combinaiei de
taste Alt+F9 sau F9, e prin meniul principal (F10 - submeniul Compile opiunea
Compile sau Make). Dac au fost semnalate erori, atunci acestea se vor corecta, apoi
se va relua compilarea, i tot aa, pn cnd compilarea se termin cu succes.
n continuare, se poate trece la etapa de execuie a programului scris (editat) i
compilat. Execuia programului se poate realiza e direct prin tastarea combinaiei de
taste Ctrl+F9, e prin meniul principal (F10 - submeniul Run opiunea Run). Even-
tualele rezultate n timpul execuiei programului sunt aate ntr-o nou fereastr.
La terminarea execuiei programului se va redeschide fereastra de editare. Dac sunt
depistate erori de execuie atunci programul se corecteaz la nivelul codului surs i
se va relua compilarea i execuia programului.
Dac se dorete terminarea sesiunii de lucru cu mediul Turbo Pascal atunci se
prsete acest mediu direct prin combinaia Alt+X sau prin meniul principal (F10,
File i Exit). Dac ierul nu a fost salvat niciodat (comanda Save = F2 din subme-
niul File) atunci se cere conrmarea salvrii dac programatorul dorete acest lucru
(prin Yes).
Mediul Turbo Pascal mparte ecranul de editare n trei zone astfel:
3.1. Mediul de programare Turbo Pascal 69
LINIA DE MEMENTO
ZONA
DE
EDITARE
MENIU PRINCIPAL
Figura 3.1: Structura general a ferestrei de editare a mediului de programare Turbo
Pascal
Fereastra de editare este utilizat pentru introducerea i corectarea programelor
scrise n limbajul Pascal. Din aceast fereastr se poate accesa meniul principal descris
mai jos prin apsarea tastei F10, apoi prin navigare cu ajutorul tastelor reprezentnd
sgeile stnga sau dreapta alegem opiunea dorit. Se poate selecta i direct o anu-
mit opiune din meniul principal prin tastarea simultan Alt+x, unde x reprezint
litera caracteristic din opiunea aleas descris mai sus cu caracter ngroat ( File =
F, Edit = E, ... Help = H ) .
File Edit Search Run Compile Debug Tools Options Window Help
Figura 3.2: Structura meniului principal a ferestrei de editare a mediului de progra-
mare Turbo Pascal
70 3. Pogramare n limbajul PASCAL
n partea de jos a ecranului se a aat linia de memento care arat cu ce taste
(combinaie de taste) putem realiza un anumit lucru direct, fr a mai trece prin
meniul principal, astfel:
F1 = Help F2 = Sace F3 = Open ALT+F9 = Compile F9 = Make ALT+F10 = Local Menu
Figura 3.3: Structura general a meniului memento a ferestrei de editare a mediului
de programare Turbo Pascal
n continuare vom descrie posibilitile (facilitile) oferite de mediul Turbo Pascal
prin meniul principal:
- File: permite ncrcarea i salvarea ierelor text ce conin programe surs
Pascal (New, Open=F3, Save=F2, ...), schimbarea directorului curent (Change
Dir), tiprirea la imprimant a programului curent (Print), executarea de comenzi
Dos (Dos Shell ) i terminarea sesiunii i prsirea mediului (Exit=Alt+X).
- Edit: permite introducerea i corectarea ierului Pascal, recuperarea tex-
telor terse (Undo=Alt+BkSp), mutarea unui bloc de text marcat ntr-o zon
tampon numit clipboard (Cut=Shift + Del), copierea unui bloc n zona tampon
(Copy=Ctrl+Ins), inserarea n poziia cursorului a unui bloc din zona tampon
(Paste=Shift+Ins), tergerea unui bloc (Clear=Ctrl+Del) i vizualizarea zonei tam-
pon (Show clipboard). Pentru a marca un bloc (o secven de program surs) se
utilizeaz simultan tasta Shift i sgeile direcionale de pe tastatur.
- Search: realizeaz funciile de cutare a unui ir de caractere (Find), de n-
locuire (Replace), precum i repetarea ultimei comenzi de cutare/nlocuire (Search
again), poziionarea direct pe o linie din programul surs precizat prin numrul ei
(Go to line number), i altele.
- Run: permite execuia unui program astfel:
- execuia ntregului program (Run=Ctrl+F9);
- execuia programului pn n poziia cursorului din programul surs (Go to
3.2. Programe simple Pascal 71
cursor=F4);
- execuia pas cu pas iar a subprogramelor ntr-un pas (Step over=F8);
- execuia pas cu pas, inclusiv a subprogramelor (Trace into=F7);
- Compile: realizarea compilarea unui program (Compile =Alt+F9), iar
destinaia programului obiect rezultat poate n memoria intern sau pe disc
(Destination Memory/Disk), compilarea automat a uniturilor dac acestea au
fost modicate (Make=F9), sau necondiionat (Build) i altele;
- Debug: permite depanarea programelor prin vizualizarea punctelor de ntreru-
pere (Breakpoints), aarea ferestrei de vizualizare a valorilor variabilelor (Watch),
aarea ferestrei de rezultate (User screen=Alt+F5), vizualizarea i modicarea
valorilor variabilelor (Evaluate/modify=Ctrl+F4), adaug expresii n fereastra de
vizualizare (Add watch = Ctrl+F7), marcarea punctelor de ntrerupere (Add break-
point i altele.
Tools: deschide fereastr de mesaje (Messages) i altele.
- Option: seteaz opiuni de compilare (Compiler), directoarele de lucru utile
(Directories), preferine de editare, mouse, startare i culori (Environment), sal-
vare conguraie (Save) ntr-un ier (Save a.).
- Window: permite operaii asupra ferestrelor de lucru astfel:
- Tile - toate ferestrele se vd simultan prin mprirea egal a ecranului,
- Cascade - ferestrele sunt aranjate una peste cealalt;
- Size/Move=Ctr+F5 - permite deplasarea i redimensionarea ferestrelor uti-
liznd sgeile i tasta shift;
- Zoom=F5 - mrete fereastra activ;
- Next=F6 - aeaz (activeaz) urmtoarea fereastr;
- Close=Alt+F3 - nchide fereastra activ;
- List = Alt+0 - tiprete lista ferestrelor de lucru.
- Help: permite ndrumarea operatorului prin submeniuri i opiuni care conduc
la explicaii i exemple.
3.2 Programe simple Pascal
Limbajul Pascal, denit de Wirth, a aprut n anul 1970, i s-a rspndit rapid
datorit calitilor sale. Wirth a urmrit s prezinte conceptele de baz din domeniul
programrii, n scopul nsuirii acestei activiti. Dei iniial limbajul a fost gndit n
scop universitar, el este folosit astzi la programarea celor mai diverse probleme, pe
toate sistemele de calcul existente [Cri, 1992].
72 3. Pogramare n limbajul PASCAL
Ca orice limbaj de programare limbajul Pascal este construit folosind un alfabet
ce conine caracterele ntlnite n scrierea obinuit i cea matematic:
- literele (mari i mici) ale alfabetului latin:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
- cifrele zecimale: 0 1 2 3 4 5 6 7 8 9
- caractere speciale: + - * / . , ; : ( ) [ ] { } etc.
Cu ajutorul lor se vor construi toate instruciunile limbajului.
Menionm c literele mici se consider identice cu literele mari, exceptnd
folosirea lor n valori de tip string (texte). De asemenea, cel puin n constante de tip
string, pe lng caracterele prezentate mai sus, sunt permise toate caracterele exis-
tente la tastatura calculatorului. De fapt multe particulariti ale limbajului depind
de implementarea lui pe calculatorul folosit.
n prezentarea care urmeaz vom folosi notaia BNF (Backus-Naur Form) pentru
a deni elementele limbajului Pascal. De exemplu prin notaia:
s ::= e1 [ e2 [ { e3 [, e4] + } e5
vom nelege c prin deniie elementul s este e1, sau e2, sau construcia { e3 [,
e4]+} e5, care reunete expresiile:
e5
e3 + e5
e3 , e4 + e5
e3 , e4 + e3 + e5
etc.
Prin scrierea unei construcii ntre acoladele { } se indic faptul c acea construcie
poate s se repete de ori cte ori (inclusiv de zero ori). Parantezele drepte ngroate
sunt folosite pentru scrierea construciilor opionale; ceea ce se a nchis ntre aceste
paranteze poate lipsi.
Se observ c n sintaxa de mai sus se folosesc metasimbolurile [, ], { i }. A nu se
confunda cu caracterele [, ], { i } permise i folosite n anumite construcii Pascal.
Pentru alte metasimboluri vom alege anumite cuvinte, scrise cu litere mici ntre
caracterele < i > i scrise cursiv.
Ca n toate limbajele de programare i n Pascal se folosesc frecvent identicatorii.
Prin identicator, notat n deniiile sintactice care urmeaz prin <id>, se nelege
o secven de litere (mari sau mici) i cifre, primul caracter ind obligatoriu o liter.
De asemenea, n construcia identicatorilor este permis i caracterul _. Acesta se
recomand s se foloseasc n scrierea identicatorilor compui din dou cuvinte unite
prin acest caracter.
3.3. Structura unui program Pascal 73
O parte dintre identicatori au un rol special n denirea instruciunilor limbajului
Pascal. Acetia se numesc cuvinte rezervate i sunt:
And Downto If Or Then Array Else
In Packed To Begin End Label Procedure
Type Case File Mod Program Until Const
For Nil Record Var Div Function Not
Repeat While Do Goto Of Set With
Cuvintele rezervate nu pot folosite n program n alt scop dect cel xat, acela
de a deni sintaxa instruciunilor Pascal.
Pentru a sublinia care sunt cuvintele rezervate, n deniiile care urmeaz ct i
n primele programe date ca exemple, vom scrie cuvintele rezervate cu litere mari.
De asemenea, aceste cuvinte vor scrise ngroat n capitolele urmtoare, pentru a le
diferenia clar de celelalte construcii datorate programatorului.
3.3 Structura unui program Pascal
Un program Pascal const dintr-un titlu, o parte de declaraii i instruciunile care
formeaz programul principal. El are urmtoarea structur general:
<program> ::= <antet_program> ; <bloc> .
unde
<antet_program> ::= Program <id> [ ( <lista_id> ) ]
iar
<bloc> ::= <lista_decl> ; <ins_compus>
Construciile <lista_decl> i <ins_compus> vor complet nelese puin mai
trziu, dup ce se vor prezenta declaraiile i instruciunile limbajului Pascal. n
general prin lista de elemente <lista_e> se nelege un simplu element <e>, sau o
succesiune de elemente
<lista_e> ::= <e> { s <e> }
unde separatorul s este virgula sau uneori caracterul ;, caz n care vom meniona
acest lucru.
n deniia blocului, elementul <decl> este metasimbolul folosit pentru declaraia
Pascal care va denit n seciunea 3.7, iar <ins> este metasimbolul folosit pentru
a nota o instruciune Pascal i va denit n seciunea 3.11.
74 3. Pogramare n limbajul PASCAL
Aa cum se va vedea mai trziu, n deniia declaraiilor de procedur se folosete
metasimbolul <bloc>. Deci un bloc care conine o procedur conine un alt bloc
care, la rndul lui, poate conine alt bloc.
Oriunde n textul programului pot incluse comentarii. Acestea sunt folosite de
ctre utilizatori n scopul mbuntirii claritii programului i a explicrii semni-
caiei unor notaii sau pri de program. Ele nu sunt luate n seam de calculator,
singurul lor scop ind acela de a oferi programatorului posibilitatea de a insera n
program explicaii utile programatorului. Un comentariu este orice text nchis ntre
acolade
<comentariu> ::= { text }
Prezentm n continuare un exemplu de program Pascal:
Exemplul 3.3.1. PROGRAM RADICAL1; { Programul 1 }
{ Exemplu de program Pascal }
Var x, r: Real; { Declaraii }
Begin { Instruciunea compus }
Repeat
Readln(x);
r := Sqrt(x); { Functia SQRT este o funcie }
{ standard pentru extragerea radicalului }
Writeln(Radical din , x, este , r);
Until x = 0
End.
3.4 Constante i variabile Pascal
Datele i rezultatele dintr-un program sunt reprezentate prin constante i variabile.
Constantele se caracterizeaz prin faptul c nu-i modic valoarea n timpul execuiei
unui program. Orice constant este precizat prin sintaxa ei i are o valoare bine
denit.
Constantele pot : numerice, ir de caractere i booleene. La rndul lor constantele
numerice pot ntregi sau reale.
Constantele ntregi sunt cele care reprezint numerele ntregi din matematic i au
sintaxa obinuit de scriere a numerelor. De exemplu, 15, 1989, -314 sunt constante
ntregi.
Constantele reale sunt cele care reprezint numerele reale. Scrierea unui numr
real poate n forma normal i n forma exponenial.
3.5. Tipuri de date 75
n forma normal este prezent att punctul zecimal "." ct i partea ntreag i
partea fracionar a numrului real. De exemplu 3.14159 1.72 -5.749 103.0 0.23 sunt
constante reale corecte. Notaiile .23A 103.+ 37.5. -123.+44 sunt greite.
n forma exponenial, un numr ntreg sau un numr real n forma normal este
urmat de litera E sau e i de un numr ntreg numit exponent. Valoarea numrului
real scris n aceast form este egal cu numrul scris n faa literei E nmulit cu 10
la puterea egal cu exponentul scris dup litera E. De exemplu:
12345E-6 este egal cu 0.012345 ;
3.123456E5 este egal cu 312345.6 .
Constanta ir de caractere este o secven de caractere (un text) nchis ntre
apostrofuri. Valoarea constantei este chiar textul nchis ntre apostrofuri. Dac este
necesar ca n text s apar i apostroful el trebuie dublat. De exemplu:
22 Decembrie 1989
LHospital
{ irul vid }
n cazul n care un singur caracter este nchis ntre apostrofuri avem o constant
de tip caracter. O constant ir de caractere este considerat ca ind rezultatul
concatenrii mai multor constante de tip caracter.
Dei s-a armat la nceput c literele mari se consider identice cu cele mici,
singura excepie este folosirea lor n constanta ir de caractere. ntr-o asemenea
constant ecare liter mare difer de litera mic corespunztoare.
Constanta boolean reprezint o valoare logic i se reprezint prin identicatorii
TRUE pentru valoarea logic "adevrat", respectiv FALSE pentru valoarea logic
"fals".
Conceptul de variabil a fost deja prezentat n seciunea 1.1.3. Ea corespunde
unei date care i poate schimba valoarea n timpul execuiei programului. Variabila
are un nume i poate primi o valoare dintr-un domeniu bine precizat de valori. n
Pascal numele unei variabile este un identicator. In limbajul Pascal ecare variabil
are un tip care trebuie s e declarat n program nainte ca variabila s e folosit.
3.5 Tipuri de date
Prin tip de date se nelege o mulime de valori i o mulime de operaii ce pot
efectuate cu valori de acest tip. Mulimea valorilor se mai numete i domeniul
tipului.
Exist mai multe posibiliti de denire a unui tip de date, unele dintre ele vor
prezentate mai trziu. Menionm c unele tipuri de date sunt predenite, iar altele
76 3. Pogramare n limbajul PASCAL
sunt denite de ctre programator n timpul scrierii programului. Dup elementele
care formeaz domeniul tipului deosebim tipuri de date simple, respectiv compuse
cu ajutorul altor tipuri. De asemenea, putem avea ca domeniu mulimea adreselor
memoriei calculatorului. Deci un tip este:
<tip> ::= <tip_simplu>[<tip_structurat>[<tip_referin>
Tipul de date <tip_simplu> se denete n continuare, iar alte dou tipuri vor
denite n seciunile urmtoare (ARRAY i RECORD).
Tipurile simple de date conin tipurile numerice INTEGER i REAL, tipul
BOOLEAN, tipul CHAR, tipul enumerare i tipul subdomeniu. Avem:
<tip_simplu> ::= <tip_real> [ <tip_ordinal>
unde
<tip_ordinal> ::= <tip_ntreg> [ <tip_boolean > [ < tip_caracter> [ <
tip_enumerare> [ <tip_subdomeniu>
Tipurile ntreg, real, boolean i caracter sunt predenite i sunt marcate prin
cuvintele INTEGER, REAL, BOOLEAN, respectiv CHAR. Deci
<tip_real> ::= Real
<tip_intreg> ::= Integer
<tip_boolean> ::= Boolean
<tip_caracter> ::= Char
Tipurile INTEGER i REAL se refer la mulimile de numere ntregi i reale, dar
mulimea valorilor ecrui tip este nit i depinde de calculatorul folosit.
Dei funciile Pascal vor indicate n seciunea urmtoare prezentm aici cteva
funcii denite asupra valorilor de tip ordinal sau de tip caracter.
Pentru ecare tip ordinal, deci i pentru tipul caracter, mulimea valorilor este
nit i ordonat. Pentru obinerea rangului elementului x n aceast mulime ordo-
nat se poate folosi funcia ORD(x). Pentru primul element p din aceast mulime
avem ORD(p) = 0. Excepie este ORD(i) pentru i ntreg, cnd ORD(i)=i. Funcia
SUCC furnizeaz succesorul unui element n aceast mulime, deci SUCC(x) reprez-
int succesorul elementului x n domeniul valorilor i este nedenit pentru ultimul
element din domeniu. Prin PRED(x) se noteaz predecesorul elementului x n dome-
niul tipului i este nedenit pentru primul element din domeniu.
Din deniiile de mai sus se deduc uor urmtoarele proprieti:
ORD( SUCC(x) ) = ORD(x) + 1;
ORD( PRED(x) ) = ORD(x) - 1.
SUCC(x) i PRED(x) trebuie s e denite.
3.5. Tipuri de date 77
3.5.1 Tipul ntreg
Domeniul tipului ntreg este submulimea numerelor ntregi cuprinse n intervalul
[-MAXINT-1, MAXINT], unde MAXINT este o constant ntreag predenit a crei
valoare depinde de calculatorul folosit i este determinat de mrimea locaiei pe
care se reprezint un numr ntreg n calculatorul respectiv (de exemplu MAXINT
=32767).
Operaia o Semnicaia lui x o y
+ adunare
- scdere
* nmulire
DIV mprire ntreag
/ mprire real
MOD Restul mpririi ntregi a lui x la y
Tabela 3.1: Operaiile tipului INTEGER
Operaiile denite ntre valori de tip ntreg sunt +, -, *, DIV, MOD i /, iar
semnicaia lor se d n Tabelul 6.2.7.2. Uneori, - se noteaz i o operaie unar.
Prin -x se nelege opusul lui x fa de operaia de adunare.
3.5.2 Tipul real
Tipul real reprezint o submulime nit de numere reale aate n intervalul [-vmax,
vmax], submulime care depinde de modul de reprezentare a numerelor reale n cal-
culatorul folosit. Deci vmax este o constant real care difer de la un calculator la
altul, dar nu e o constant predenit ca MAXINT n cazul tipului INTEGER.
Operaiile denite ntre valori de tip real sunt adunarea, scderea, nmulirea i
mprirea, notate prin +, -, *, respectiv / . De remarcat c aceste operaii sunt
denite i cnd un operand este ntreg iar cellalt real, rezultatul ind real, datorit
conversiei implicite a tipului ntreg la real.
Menionm c n reprezentarea oricrui numr real n calculator se rein un numr
nit de cifre semnicative. Din aceast cauz rezultatul unei operaii cu numere reale
este aproximativ. Pentru a nelege exact aceste armaii este necesar cunoaterea
reprezentrii numerelor n calculator.
78 3. Pogramare n limbajul PASCAL
3.5.3 Tipul boolean
Domeniul tipului boolean const din mulimea valorilor logice "fals" i "adevrat",
marcate prin constantele FALSE, respectiv TRUE. Ordinea este FALSE < TRUE.
Operaiile logice binare sunt marcate prin AND (conjuncia logic) i OR (dis-
juncia logic), iar negaia (operaie logic unar) prin NOT. Operatorii relaionali
au n acest caz semnicaii logice. Deci prin =, <>, <=, >=, sunt notate echivalena,
neechivalena (SAU exclusiv), implicaia, respectiv implicaia invers.
3.5.4 Tipul caracter
Tipul caracter este marcat prin identicatorul CHAR i reprezint mulimea carac-
terelor cu care lucreaz calculatorul respectiv. Principial, ordinea acestor caractere
poate s difere de la calculator la calculator. ns indiferent de calculator, limbajul
Pascal cere ca mulimea cifrelor zecimale s e codicat compact (diferena codurilor
a dou cifre consecutive s e 1), iar submulimile literelor mari i a literelor mici s
e ordonate alfabetic.
Nu exist operaii denite asupra valorilor de tip CHAR. Pe lng funciile denite
pentru argument de orice tip ordinal, pentru tipul caracter mai ntlnim i funcia
CHR. Pentru i ntreg, CHR(i) furnizeaz caracterul de rang i din domeniul tipului
CHAR. S observm c
ORD( CHR(i) ) = i
i
CHR( ORD(c) ) = c .
3.5.5 Tipul enumerare
Tipul enumerare se specic prin scrierea valorilor acestui tip ntre paranteze:
<tip-enumerare> ::= ( <lista-id> )
identicatorii din paranteze constituind valorile tipului enumerare denit. Ordinea
lor este cea dat de ordinea identicatorilor n list. Nu este permis ca o valoare a
acestui tip (deci un identicator) s e reutilizat n deniia altui tip.
Exemple de tip enumerare:
Exemplul 1: (LUNI, MARTI, MIERCURI, JOI, VINERI, SAMBATA, DU-
MINICA)
Exemplul 2: (PRIMAVARA, VARA, TOAMNA, IARNA)
Pentru aceste exemple avem:
PRED(TOAMNA) = VARA
SUCC(JOI) = VINERI
3.6. Expresii Pascal 79
ORD(LUNI) = 0
ORD(IARNA) = 3 .
Menionm c valorile variabilelor de tip enumerare nu pot citite i nici tiprite.
3.5.6 Tipul subdomeniu
Tipul subdomeniu poate denit din orice tip ordinal prin precizarea limitelor infe-
rioar i superioar care denesc valorile subdomeniului. Tipul ordinal pentru care
se denete subdomeniul se numete tip de baz al subdomeniului. Avem:
<tip-subdomeniu> ::= constanta1 .. constanta2
unde constanta1 i constanta2 sunt valori ale tipului ordinal de baz care satisfac
inegalitatea
Ord(constanta1) <= Ord(constanta2).
De exemplu:
- subdomeniul ntregilor de la 1 pn la 20: 1..20
- subdomeniul zilelor lucrtoare: LUNI .. VINERI
- caracterele cifre zecimale: 0 .. 9.
3.6 Expresii Pascal
O expresie Pascal este format din operanzi i operatori. Deci o expresie Pascal are
forma:
a[1] o[1] a[2] o[2] ... a[n] o[n] a[n+1]
unde a[i], i = 1, 2, ..., n+1, sunt operanzii expresiei, iar o[i], i = 1, 2, ..., n,
sunt operatorii expresiei. Deoarece n >= 0, pot exista expresii formate dintr-un
singur operand. Acest operand poate avea orice tip Pascal, el ind i tipul expresiei.
n funcie de tipurile operanzilor deosebim expresii aritmetice, expresii relaionale,
expresii logice i expresii ordinale.
ntruct n denirea expresiilor se folosesc i funciile, prezentm cteva funcii
Pascal.
3.6.1 Funcii predenite
Pe lng operaiile algebrice prezentate deja, exist i funcii frecvent folosite n re-
zolvarea unor probleme, cum ar extragerea rdcinii ptrate, calculul valorii unei
funcii trigonometrice, calculul logaritmilor etc. Pentru efectuarea acestor calcule n
limbajul Pascal exist funcii predenite, funcii pe care le dm n tabelul 3.2.
80 3. Pogramare n limbajul PASCAL
Notaia S e m n i f i c a i a
abs(i) Valoarea (ntreag) absolut a ntregului i
abs(x) Valoarea (real) absolut a realului x
sqr(i) Ptratul ntregului i
sqr(x) Ptratul numrului real x
int(x)
Partea ntreag a numrului real x dac x>0,
respectiv int(abs(x)) dac x<0
trunc(x) ntregul obinut din numrul real x prin eliminarea prii fracionare
round(x) Cel mai apropiat ntreg de numrul real x
frac(x) Valoarea x - int(x), x real
exp(x) e la puterea x, pentru x ntreg sau real
sin(x) sinusul lui x
cos(x) cosinusul lui x
arctan(x) arctangenta din x, unde x este masura unghiului in radiani
ln(x) logaritm natural din x, x ntreg sau real > 0
sqrt(x) radical din x, x>=0
succ(i) succesorul valorii ordinale i
pred(i) predecesorul valorii ordinale
ord(e) numrul de ordine al valorii e n tipul expresiei ordinale
chr(i) caracterul de ordin i n tipul CHAR
odd(i)
funcie logic cu valoarea TRUE dac i este impar i
FALSE dac i este par
Tabela 3.2: Funcii Pascal predenite
3.6. Expresii Pascal 81
3.6.2 Expresii aritmetice
Expresiile aritmetice sunt expresii n care operanzii sunt valori numerice ntregi sau
reale. Operatorii sunt cei permii de tipurile ntreg i real; se cere ca operaia care
leag doi operanzi s e denit n tipul acestor operanzi. Operanzii unei expresii
aritmetice pot :
- constante numerice;
- variabile simple de tip numeric;
- elemente de tablou de tip numeric;
- funcii numerice;
- subexpresii aritmetice, adic o expresie aritmetic, eventual precedat de semnul
-, nchis ntre paranteze.
Deci o expresie aritmetic, notat <exp-a>, se poate deni astfel:
<exp-a> ::= <term> | <exp-a> + <term> | <exp-a> - <term>
unde
<term> ::= <factor> | <term> * <factor> | <term> / <factor> | <term> DIV
<factor> |
<term> MOD <factor>
iar
<factor> ::= <constant numeric fr semn> |
<variabil de tip numeric> |
<element de tablou de tip numeric> |
<funcie de tip numeric> |
( <exp-a> ) |
( -<exp-a> )
Menionm c prioritatea operaiilor este cea cunoscut i folosit n matematic.
Pentru a indica o alt ordine se vor folosi parantezele. De asemenea, menionm c
expresiile aritmetice denite mai sus pot precedate de operaia unar -, cu semni-
caia cunoscut din matematic.
Tipul unei expresii aritmetice este ntreg dac toi operanzii sunt ntregi i expresia
nu conine operatorul /. Dac ns expresia conine acest operator, sau dac exist
cel puin un operand de tip real, atunci tipul expresiei este real.
n evaluarea unei expresii aritmetice se calculeaz mai nti toi operanzii. O
subexpresie aritmetic este tot un operand. n evaluarea ei se procedeaz ca la o
expresie aritmetic; deci dac toi operanzii sunt ntregi i operaiile sunt denite n
tipul ntreg atunci rezultatul este ntreg.
Astfel, valoarea expresiei 5 div 2 + 1.0 este numrul real 3.0 i nu 3.5, ntruct
primul operand al adunrii are valoarea ntreag 2 deoarece 5 div 2 este o expresie de
82 3. Pogramare n limbajul PASCAL
tip ntreg.
3.6.3 Expresii relaionale
Expresia relaional are scopul de a permite scrierea n Pascal a unor relaii mate-
matice care pot adevrate sau false. Ea are forma
<e1> <op.rel.> <e2>
unde <e1> i <e2> sunt expresii care au acelai tip ordinal, sau au tipul real, sau
sunt elemente de acelai tip n care s-a denit operaia relaional <op.rel.>, iar
<op.rel.> ::= < [ <= [ = [ > [ >= [ <>
Valoarea expresiei relaionale de mai sus este TRUE dac ntre valorile expresiilor
<e1> i <e2> are loc relaia indicat i este FALSE n caz contrar. De fapt, aceste
simboluri noteaz relaiile cunoscute din matematic.
Atenie ns la relaia de egalitate ntre dou numere reale. Din cauza unor aproxi-
mri, calculele cu numere reale nu sunt exacte. De exemplu, dac x=i/3, expresia
relaional x = x*3 poate fals deoarece, din cauza reprezentrii interne calculele
cu numere reale nu sunt exacte, iar x*3 nu este o valoare ntreag, ci o valoare real
foarte apropiat de i dar, totui, diferit de i.
Tot ca exemplu, menionm c dac A i B sunt dou mulimi de acelai tip atunci
expresia A = B va avea valoarea logic TRUE n cazul cnd mulimile A i B sunt
egale i FALSE n caz contrar.
3.6.4 Expresii logice
Expresia logic este o expresie Pascal n care operatorii pot operatori logici binari:
And pentru conjuncia logic;
Or pentru disjuncia logic,
iar operanzii pot :
- constante logice;
- variabile de tip logic;
- elemente de tablou de tip logic;
- funcii logice;
- expresii relaionale;
- subexpresii logice, adic expresii logice nchise ntre paranteze;
- negaia unui operand logic din cei de mai sus, deci Not <operand logic>;
- expresia x in M unde M este o mulime i x o variabil avnd tipul de baz al
mulimii M.
3.7. Declaraii Pascal 83
n determinarea valorii unei expresii logice se evalueaz mai nti operanzii i
apoi operaiile logice binare n ordinea prioritii lor: mai nti conjunciile logice
(operaiile And) i apoi disjunciile logice (operaiile logice Or). Operaiile logice cu
aceeai prioritate se evalueaz de la stnga spre dreapta n ordinea scrierii lor.
Menionm c este necesar ca toi operanzii s e denii, altfel este posibil ca eval-
uarea unei expresii logice s se termine cu eroare. Astfel, n expresia logic (i<=10)
And (x[i]>0) este posibil s ajungem la o eroare dac x are doar 10 componente i i
are valoarea 11, ntruct x[11] nu este denit, deci al doilea operand nu are sens. Un-
ele implementri nu mai evalueaz al doilea operand n cazul n care primul operand
este FALSE, valoarea expresiei ind n acest caz FALSE.
De asemenea, menionm c ntr-o expresie logic n care apar operatorii + i
And, ultimul considerat mai prioritar dect primul, este posibil s se scrie expresii
fr sens. Astfel, expresia 0 < A+B And C < D este interpretat ca i expresia 0 <
A+(B And C) < D care nu are sens. De aceea, se cere ca, n astfel de cazuri, s se
foloseasc parantezele pentru precizarea prioritii operaiilor.
3.7 Declaraii Pascal
ntr-un program Pascal trebuie precizate toate variabilele i denumirile simbolice,
nainte de a le folosi. Spunem c o entitate este declarat atunci cnd ea apare ntr-o
declaraie Pascal, n care se precizeaz tipul ei, eventual alte informaii despre ea,
utile att programatorului ct i compilatorului. Deci, orice obiect pe care dorim s-l
folosim ntr-un program Pascal, trebuie mai nti declarat n partea de declaraii a
programului.
Dup obiectele pe care le reprezint deosebim urmtoarele declaraii Pascal:
- declaraii de etichete;
- declaraii (deniri) de constante;
- declaraii (deniri) de tipuri;
- declaraii de variabile;
- declaraii de subprograme.
Deci
<decl> ::= <def-et> [ <def-const> [ <def-tip> [ <def-var> [ <def-subp>
Dei nu este obligatoriu s le ntlnim pe toate n aceeai unitate de program,
atunci cnd sunt prezente ele trebuie scrise respectnd ordinea enumerrii de mai sus.
De asemenea, n limbajul Pascal standard ntr-o unitate de program ecare declaraie
poate apare cel mult odat. Limbajul Turbo Pascal a renunat la aceste restricii.
84 3. Pogramare n limbajul PASCAL
n deniia sintactic a unui program Pascal s-a folosit metasimbolul <lista-decl>.
Evident, elementele acestei liste sunt declaraii, separatorul folosit ind caracterul ;.
Dei exist, nu vom folosi declaraia de etichete. Programarea structurat pretinde
renunarea la instruciunea GOTO, instruciune care cere folosirea etichetelor. Prin
exemplele pe care le prezentm artm c acest lucru, de altfel demonstrat, este
posibil.
Observaie. Evit s foloseti instruciunea GOTO.
3.8 Denirea constantelor
Prin metasimbolul <def_const> am notat o denire de constante cu nume, care are
sintaxa
Const <id>=<constanta> { ; <id>=<constanta> }
unde <id> este un identicator care va nota numele constantei denite, iar con-
stanta care urmeaz va preciza valoarea constantei denite. Ea poate numeric,
boolean, sau un ir de caractere. De exemplu:
Const
PI = 3.141592653;
ORDIN = 5; N = 4;
MARCA = ...
denete o constant cu numele PI i valoarea precizat dup semnul egal, alte dou
constante cu numele ORDIN i valoarea 5, respectiv cu numele N i valoarea 4 i
constanta cu numele MARCA cu valoarea egal cu irul , compus din trei puncte.
Denirea unei constante este necesar atunci cnd ne referim la ea n mai multe
pri ale programului, pentru a prescurta scrierea, sau pentru a permite modicarea
ulterioar uoar a programului.
Observaie. Folosete constante cu nume n locul celor anonime.
3.9 Denirea tipurilor
Declaraia <def-tip> de denire a unor tipuri noi are sintaxa
Type <id>=<tip> { ; <id>=<tip> }
unde <id> este un identicator ce reprezint numele tipului denit, iar <tip> este
un tip denit cu ajutorul tipurilor deja cunoscute (predenite, sau denite anterior
de utilizator). De exemplu, prin declaraia:
Type domindici = 1..12
3.10. Declararea variabilelor 85
se denete un tip cu numele domindici care este un subdomeniu al lui INTE-
GER, format din toate numerele ntregi cuprinse intre cele dou limite menionate,
1, respectiv 12.
3.10 Declararea variabilelor
Toate variabilele folosite ntr-un program Pascal trebuie declarate nainte de a
folosite. Declaraia de variabile, notat prin metasimbolul <def-var>, are sintaxa
Var <lista-id> : <tip> { ; <lista-id> : <tip> }
unde <lista-id> este o list de identicatori, iar <tip> este un tip predenit sau
denit de utilizator. Prin ea se declar toate variabilele din lista de identicatori
<lista-id> ca avnd tipul precizat dup caracterul :. De exemplu, prin
Var M, N, I, J, K: Integer;
X, Y, Z: Real
se declar cinci variabile de tip ntreg, avnd numele M, N, I, J i K i trei variabile
de tip real cu numele X, Y, i Z. Prin declaraia
Var A: Array[1..9] Of Real
se declar un vector A cu nou componente. Tipul variabilei A, cel de "vector
cu 9 componente reale", este un tip anonim i nu mai poate folosit n alt parte
a programului Pascal. Chiar i n aceeai declaraie de variabile folosirea aceleai
construcii pentru a deni variabila B tot "vector cu 9 componente reale" se consider
diferit de prima. De exemplu prin declaraia
Var A: Array[1..9] Of Real;
B: Array[1..9] Of Real
s-au declarat doi vectori, dar care se consider c nu au acelai tip, spre deosebire de
declaraia
Var C, D : Array[1..9] Of Real
prin care s-au denit dou variabile de acelai tip.
Observaie. Folosete tipuri de date cu nume n locul celor anonime.
Respectarea acestei reguli conduce, pe lng cele artate mai sus, la creterea
claritii textului i a posibilitii de modicare a textului surs (schimbarea structurii
marcat prin acest nume se poate face ntr-un singur loc, cel al denirii ei).
Variabilele i celelalte elemente declarate ntr-o procedur sunt locale n aceast
procedur, deci pot folosite n orice instruciune a procedurii, dar nu i n afara ei.
De asemenea, ele pot folosite n orice alt procedur declarat n interiorul acestei
proceduri, ele ind variabile globale pentru acestea, aa cum se va arta n seciunea
3.12.
86 3. Pogramare n limbajul PASCAL
3.11 Instruciuni Pascal
Exist mai multe instruciuni Pascal, toate notate prin metasimbolul <ins>. Exist
instruciuni Pascal simple n interiorul crora nu se a alte instruciuni i instruciuni
structurate, compuse din alte instruciuni. Deci
<ins> ::= <ins_simple> [ <ins_structurate>
unde
<ins_simple> ::= <ins_atribuire> [ <ins_vid> [ <apel_procedur>
iar
<ins_structurate> ::= <ins_compus> [ <ins_condiionale> [ <ins_iterative>
Aceste instruciuni vor prezentate n continuare.
3.11.1 Instruciunea de atribuire
Instruciunea de atribuire are scopul de a atribui valori unor variabile. Ea are sintaxa
<ins_atribuire> ::= <variabila> := <expresie>
unde <variabila> i <expresie> sunt de acelai tip, exceptnd cteva cazuri
menionate mai jos. Tipurile tv i te ale elementelor <variabila> i <expresie>
pot ntreg, real, boolean, enumerare sau orice tip structurat cunoscut n programul
n care apare instruciunea, cu excepia tipului ier.
Instruciunea cere mai nti evaluarea expresiei din partea dreapt a semnului de
atribuire ":=". Dac tv i te sunt identice atunci valoarea expresiei este atribuit vari-
abilei din stnga semnului de atribuire. Dac aceste tipuri difer atunci se semnaleaz
eroare, exceptnd patru cazuri care vor prezentate n continuare:
1) Astfel, dac te este Integer iar tv este Real atunci se convertete valoarea
ntreag a expresiei ntr-o valoare real care se atribuie variabilei.
2) Dac tv i te sunt tipuri enumerare sau subdomeniu cu acelai tip de baz i
dac valoarea expresiei aparine tipului tv, aceast valoare se atribuie variabilei.
3) Dac tv i te sunt mulimi atunci este posibil ca unul sau ambele tipuri s
e subdomenii ale aceluiai tip ordinal. Atribuirea este permis dac valorile din
mulimea rezultat sunt incluse n tipul de baz al variabilei din stnga semnului de
atribuire.
4) A patra excepie se refer la tipul String; tv i te putnd tipuri String
diferite. Atribuirea este corect dac valoarea ei se poate atribui variabilei din stnga
atribuirii.
Sintactic, n partea stng a semnului de atribuire, <variabila> poate o variabil
simpl sau o component a unui tablou sau alt tip de dat structurat. De asemenea,
ea poate un tablou atunci cnd i n partea dreapt este un tablou de acelai tip. n
3.11. Instruciuni Pascal 87
acest caz prin A := B, se nelege o scriere condensat a atribuirilor A[i]:=B[i] pentru
toate valorile indicelui i aate n tipul de index folosit n denirea tablourilor A i B.
n general, este posibil atribuirea A := B cnd i A i B sunt variabile de acelai
tip. n toate cazurile se cere ca partea dreapt a atribuirii s aib o valoare anterioar,
altfel vom spune c variabila B este neiniializat, iar atribuirea va conduce la erori
logice n execuia programului.
3.11.2 Instruciunea compus i instruciunea vid
n denirea unor instruciuni structurate sau a construciei <bloc> din seciunea
3.3, se cere folosirea unei singure instruciuni, aa cum se va vedea n continuare.
Pentru a putea include n aceste locuri grupuri de instruciuni, n Pascal este posibil
s denim o succesiune de instruciuni ca o singur entitate. Aceast entitate se
numete instruciune compus i are sintaxa
Begin
<ins>;
{<ins> }
End
n limbajul Pascal caracterul ; separ dou instruciuni; el nu are rolul de a
marca sfritul acestora. Adesea ns ntlnim caracterul ; n faa cuvntului End.
n acest caz se consider c ntre ; i End se a o instruciune vid:
<ins-vid> ::=
Instruciunea vid are efect nul i n cazul menionat mai sus ea nu este necesar.
Este posibil s ntlnim situaii n care avem nevoie de aceast instruciune. De
exemplu, dac la ndeplinirea unei condiii dorim s mergem la sfritul programului
fr a mai executa nimic, vom face un salt la o instruciune vid, ultima instruciune
din programul respectiv.
Subliniem ns c este interzis folosirea instruciunii vide, deci i a caracterului
; n faa cuvntului Else.
3.11.3 Citirea i scrierea datelor
Pentru transferul datelor ntre memoria intern i suportul extern de date se folosesc
procedurile Read i Write. Dei procedurile vor prezentate mai trziu, precizm
semnicaia acestor dou proceduri pentru a putea da n continuare exemple complete
de programe Pascal.
Procedura Read se folosete pentru transferul datelor n memoria intern. Sintaxa
apelului acestei proceduri este:
88 3. Pogramare n limbajul PASCAL
Read ( <lista-var> )
unde <lista-var> este o list de variabile care pot avea unul din tipurile ntreg,
real, sau caracter.
Efectul acestui apel este de atribuire a unei valori ecrei variabile prezente n
lista de variabile. Valorile se iau de pe suportul extern ncepnd din punctul n care
s-a ajuns dup citirea anterioar. Valorile sunt astfel luate nct s corespund tipului
variabilei corespunztoare. Dac acest lucru nu este posibil atunci se va semnala o
eroare n execuie.
Ca exemplu, dac X este o variabil de tip ntreg iar U i V sunt variabile de tip
caracter, instruciunea
Read(X, U, V)
cere atribuirea unei valori ntregi variabilei X i a cte o valoare caracter vari-
abilelor U i V. Dac pe suportul extern se a 125 A atunci X va primi valoarea
125, variabila U va primi valoarea (caracterul blanc), iar V va primi valoarea A.
Dac ns suportul extern conine 12.4 A execuia se va termina cu eroare ntruct
valoarea 12.4 nu are tipul ntreg.
Tot cu eroare se va termina execuia cnd pe suportul extern avem TEXT 25
ntruct prima valoare ntlnit nu este un numr ntreg.
Procedura Write asigur transferul informaiei din memoria intern pe suportul
extern. Apelul procedurii are forma
Write ( <lista-write> )
unde <lista-write> este o list de expresii Pascal de orice tip.
Efectul acestui apel este tiprirea valorilor expresiilor din <lista-write>. Binene-
les, c pentru a tipri aceste valori se vor evalua mai nti expresiile prezente n list.
Valorile expresiilor sunt tiprite dar nu sunt reinute n memorie i nu pot folosite
n alte instruciuni din program. Dac dorim s folosim valoarea unei expresii i n
alte instruciuni, atunci o vom atribui mai nti unei variabile i vom folosi aceast
variabil att n <lista-write> ct i n celelalte instruciuni.
Pentru a nelege mai bine procesul de introducere i extragere a datelor vom
folosi noiunea de nregistrare. Prin nregistrare vom nelege informaia pe care o
transfer la un moment dat o unitate periferic. Astfel, pentru un cititor de cartele
o nregistrare era o cartel perforat. Pentru imprimant o nregistrare va un rnd
al hrtiei de scris (listingului), a crei lungime depinde de imprimanta folosit (de
obicei 80 sau 132 de caractere). Pentru un calculator personal o nregistrare va un
rnd al ecranului, sau o succesiune de caractere de lungime variabil, terminat cu
un caracter special EOLN (End Of Line).
Pe suportul extern datele de transferat se a scrise, sau vor tiprite pe o suc-
cesiune de nregistrri. La procedurile Read i Write atunci cnd se epuizeaz o
3.11. Instruciuni Pascal 89
nregistrare se ncepe o alt nregistrare. Adeseori este ns necesar s se treac la o
alt nregistrare nainte de a epuizat precedenta. Pentru aceasta se pot folosi pro-
cedurile READLN i WRITELN, care au sintaxa i semnicaia procedurilor READ,
respectiv WRITE, dar cer n plus ca la terminarea execuiei lor s se treac la n-
ceputul unei noi nregistrri.
3.11.4 Instruciuni condiionale
Exist dou instruciuni Pascal care permit execuia unor instruciuni n funcie de
ndeplinirea unor condiii: instruciunile IF i CASE.
Instruciunea If
Instruciunea If are sintaxa
If <cond> Then <ins1>
sau
If <cond> Then <ins1> Else <ins2>
unde <cond> este o expresie logic iar <ins1> i <ins2> sunt instruciuni Pascal.
Subliniem c dup cuvntul Then i n faa cuvntului Else nu poate scris caracterul
;, deci nu poate apare o instruciune vid.
n ambele variante instruciunea cere mai nti evaluarea expresiei logice <cond>.
Dac valoarea obinut este TRUE atunci se execut instruciunea <ins1> cu care se
ncheie execuia instruciunii If. Dac valoarea obinut este FALSE atunci, n cazul
variantei a doua se execut instruciunea <ins2>, iar n cazul primei variante nu se
execut nimic.
Aceast instruciune permite scrierea in Pascal a structurilor alternative i este
echivalent ca semnicaie cu propoziia Pseudocod:
DAC <cond> ATUNCI <ins1>
ALTFEL <ins2>
SFDAC
Ca un prim exemplu, pentru a efectua atribuirea V:= [X[ n Pascal putem scrie:
If X < 0 then V := -X else V := X
Exemplul 3.11.1. Exemplu de rezolvare a ecuaiei de gradul 2.
ALGORITMUL Ecgr2 ESTE:
CITETE a, b, c;
90 3. Pogramare n limbajul PASCAL
FIE d := b*b - 4*a*c;
DAC < 0 ATUNCI kod := 0;
ALTFEL kod := 1; r := @radical din d;
x1 := (-b-r)/(a+a); x2 := (-b+r)/(a+a);
SFDAC
DAC kod = 0 ATUNCI TPRETE(Ec. nu are rad. reale);
ALTFEL TIPRETE(Radacinile ec. sunt:, x1, x2);
SFDAC
SFECGR2
Programul Pascal corespunztor este urmtorul:
Program Ecgr2; { Rezolvarea}
{ecuatiei de gradul 2}
Var a, b, c, {Coecienii ecuaiei}
d, {Discriminantul ecuaiei}
r, {variabil de lucru}
x1, x2: Real; {Rdcinile}
kod: Integer; {kod =0 pt. rd.reale, 1_complexe}
Begin
Writeln(Se rezolva ecuatia de gradul doi);
Writeln(Dati coecientii a, b, c); Readln(a, b, c);
d := b*b - 4*a*c;
If d < 0 then kod := 0
Else
Begin
kod := 1; r := sqrt(d);
x1 := (-b-r)/(a+a);
x2 := (-b+r)/(a+a)
End;
If kod = 0
Then Write(Ec. nu are radacini reale)
Else
Write(Radacinile ecuatiei sunt:, x1, x2);
End.
Instruciunea Case
Instruciunea Case permite selectarea unei instruciuni dintr-o mulime de instruci-
uni marcate, n funcie de valoarea unui selector. Sintaxa instruciunii este
3.11. Instruciuni Pascal 91
Case <eo> of
<lista-c> : <ins> { ;
<lista-c> : <ins> }
[ Else <ins> ]
End
unde <eo> este o expresie de tip ordinal, <lista-c> este o list de constante-case,
ecare constant-case avnd tipul ordinal al expresiei <eo>. n <lista-c> n locul
unei constante poate apare i un subdomeniu c1...c2 pentru o scriere mai condensat
n cazul cnd constantele sunt consecutive.
Execuia instruciunii Case cere mai nti evaluarea expresiei <eo>, obinndu-se
o valoare v, care constituie valoarea selectorului. Apoi, se caut n listele de constante-
case constanta egal cu v i se execut instruciunea a crei etichet este chiar v.
Dac nu exist nici o instruciune cu eticheta v atunci, n cazul c este prezent
cuvntul Else se execut instruciunea ce urmeaz dup acest cuvnt, altfel nu se
execut nici o instruciune.
Exemplul 3.11.2. Ca exemplu, vom scrie un program Pascal care calculeaz valoarea
unei funcii
Program Valf; {Valoarea unei funcii }
{ Instruciunea Case }
Var x, f : Real;
a : Char;
Begin
Writeln(Se calculeaza f(x,a). Introducei x si a);
Read(a, x);
Case a of
A: f := 5*x-8; { cazul a = A }
B: f := sin(x); { cazul a = B }
C: f := 3*x+1 { cazul a = C }
End {Case};
Write(f(, x, ,, a, )=, f)
End.
3.11.5 Instruciuni repetitive
n Pascal exist trei instruciuni care permit execuia repetat a unui grup de in-
struciuni i anume instruciunile For, While i Repeat.
92 3. Pogramare n limbajul PASCAL
Instruciunea For
Aceast instruciune permite execuia repetat a unei instruciuni n funcie de val-
oarea unui contor. Ea are sintaxa
For <v> := <e1> to <e2> do <ins>
sau
For <v> := <e1> downto <e2> do <ins>
Aici <v> este un identicator de variabil numit contor, iar <e1> i <e2> sunt
expresii, toate trei avnd acelai tip ordinal (deci nu pot avea tipul real). Valorile vi
i vf ale expresiilor <e1> i <e2> se calculeaz o singur dat la nceputul execuiei
instruciunii For. Variabila contor <v> va lua valori ntre limitele vi i vf, cresctor
dac n instruciune gureaz cuvntul To, i descresctor dac n instruciune -
gureaz cuvntul Downto. Semnicaia acestei instruciuni este dat prin urmtorul
algoritm:
Calculeaz valorile vi i vf ale expresiilor e1, respectiv e2;
DAC c1 ATUNCI
FIE v := vi;
REPET
@Execut instruciunea ins;
DAC c2 ATUNCI
v:=e3;
SFDAC
PNCND c3 SFREP
SFDAC
unde condiiile c1, c2 i c3 i expresia e3 sunt denite n continuare:
Condiii To Downto
c1 vi = vf vi >= vf
c2 v < vf v > vf
c3 v >=vf v <= vf
e3 este Succ(v) Pred(v)
Tabela 3.3: Denirea condiiilor pentru execuia instruciunii For
3.11. Instruciuni Pascal 93
Contorul v poate folosit n instruciunea <ins> dar nu este permis modicarea
valorii sale. Dei unele implementri permit acest lucru, recomandm s nu se modice
valoarea variabilei contor v n instruciunea <ins>.
Astfel, n mediul Turbo-Pascal nu se consider eroare modicarea variabilei con-
tor, dar execuia unui astfel de program devine imprevizibil. De exemplu, execuia
urmtoarelor instruciuni intr ntr-un ciclu innit:
For i:=1 to 5 do {La execuia acestui grup se vor tipari}
Begin { int=1, apoi 3, 5, 7, 9, ... }
Writeln(int=,i); { deci se intra in ciclu innit}
Readln(j); { in Turbo 7.0 ! }
i:=i+1;
End
Unii programatori folosesc intenionat, atunci cnd e posibil acest lucru, modi-
carea valorii contorului pentru a fora ieirea din ciclu. O astfel de programare ncalc
semnicaia instruciunii FOR i nu este recomandabil [Ata, 1996].
Ca un prim exemplu de folosire a instruciunii FOR dm un program care tiprete
toi divizorii proprii ai numrului natural n>2.
Exemplul 3.11.3.
Program Divizori; { Programul 4.4: Divizorii lui n }
Var n,i : Integer;
Begin
Writeln(Se tiparesc divizorii lui n);
Write(Dati n=); Readln(n);
For i:=2 to n-1 do
If n Mod i = 0 Then
Writeln(i);
End.
Instruciunea While
Aceast instruciune are sintaxa
While <cond> Do <ins>
unde <cond> este o expresie logic iar <ins> este o instruciune Pascal. Semnicaia
instruciunii While este aceeai cu a propoziiei Pseudocod:
CTTIMP <cond> EXECUT
<ins> SFCT
94 3. Pogramare n limbajul PASCAL
Deci execuia instruciunii While cere urmtoarele:
1. evaluarea expresiei logice <cond>;
2. dac valoarea expresiei este True atunci se execut instruciunea <ins> i se
revine la pasul 1, altfel execuia se termin.
Cu alte cuvinte, ea cere execuia repetat a unei instruciuni Pascal n funcie
de valoarea de adevr a unei expresii logice. Dac iniial expresia logic este fals
execuia instruciunii respective nu va avea loc niciodat.
Ca exemplu, vom transcrie n Pascal urmtorul algoritm care gsete primele n
numere prime [Moc, 1993].
Exemplul 3.11.4.
Pseudocod:
ALGORITMUL PRIME ESTE: {Determina primele n numere prime}
CITETE n;
FIE k:=2; p[1]:=2; p[2]:=3; i:=5;
CTTIMP k<n EXECUT
FIE j:=1;
CTTIMP j<=k i (i mod p[j] <> 0) EXECUT
j:=j+1;
SFCT
DAC j>k ATUNCI
k:=k+1;
p[k]:=i;
SFDAC
i:=i+2;
SFCT
TIPRETE p[j], j=1,n;
SF-PRIME
Programul Pascal:
Program Prime; { Calculeaz primele n numere prime }
Var n,i,j,k : Integer;
p : Array [1..200] of Integer;
Begin
Writeln(Se tiparesc primele n numere prime!);
Write(Dati n=); Readln(n);
k:=2; p[1]:=2; p[2]:=3; i:=5;
While k<n do
3.11. Instruciuni Pascal 95
Begin
j:=1;
While (j<=k) and (i mod p[j] <> 0) do
j:=j+1;
If j>k Then
Begin
k:=k+1;
p[k]:=i
End;
i:=i+2
End;
Writeln(Primele ,n, numere prime sunt:);
For j:=1 To n Do Writeln( p(,j,)=,p[j])
End.
Instruciunea Repeat
Aceast instruciune permite execuia repetat a unui grup de instruciuni. Ea are
sintaxa
Repeat <ins> { ; <ins> } Until <cond>
unde <ins> este o instruciune Pascal, iar <cond> este o expresie logic. Instruci-
unea este echivalent cu urmtoarea propoziie Pseudocod:
REPET
<ins> { <ins> }
PNCND <cond> SFREP
Semnicaia instruciunii este urmtoarea:
1. se execut instruciunile scrise ntre cuvintele Repeat i Until;
2. se evalueaz expresia logic <cond>. Dac valoarea expresiei este True atunci
execuia se termin, altfel se revine la pasul 1.
Ca exemplu de folosire a instruciunii Repeat vom transcrie n Pascal urmtorul
algoritm pentru ordonarea descresctoare a unui ir de numere reale.
Exemplul 3.11.5.
Pseudocod:
ALGORITMUL Ordon ESTE: {Ordoneaz descresctor}
{numerele x[1], ... , x[n]}
CITETE n, (x[i],i=1,n);
96 3. Pogramare n limbajul PASCAL
REPET k:=0;
PENTRU i:=1,n-1 EXECUT
DAC x[i]<x[i+1] ATUNCI
k:=1;
t:=x[i];
x[i]:=x[i+1];
x[i+1]:=t;
SFDAC
SFPENTRU
PNCND k=0 SFREP
TIPRETE x[i],i=1,n;
SFALGORITM
Programul Pascal corespunztor este:
Program Ordon; {Ordonarea unui sir de numere}
Var t : Real;
n,i,k : Integer;
x : Array [1..100] Of Real;
Begin
Writeln(Se ordoneaz o secventa de numere reale);
Write(Nr.termenilor=); Readln(n);
Writeln(Dati termenii);
For i:=1 to n do
Read(x[i]);
Writeln;
Writeln(Sirul initial este:);
For i:=1 to n do
Write(x[i]:8:1);
Repeat
k:=0;
For i:=1 to n do
If x[i] < x[i+1] Then
Begin
k:=1;
t:=x[i];
x[i]:=x[i+1];
x[i+1]:=t
End;
3.12. Subprograme Pascal 97
Until k=0;
Writeln( Sirul ordonat este:);
For i:=1 to n do
Write(x[i]:8:2);
End.
3.12 Subprograme Pascal
Subprogramele n Pascal corespund subprogramelor din Pseudocod. Importana sub-
programelor n programare a fost deja subliniat n seciunea 1.1.7. n scopul re-
folosirii subalgoritmilor i subprogramelor e bine ca pentru orice problem s descriem
un subalgoritm pentru rezolvarea ei.
Observaie. Concepe subalgoritm i scrie subprogram pentru orice problem care ar
putea rentlnit n viitor.
Sintaxa subprogramelor Pascal
Ca i n alte limbaje de programare i n limbajul Pascal exist dou tipuri de subpro-
grame: funcii i proceduri. Denirea acestor subprograme n cadrul unui program
Pascal se face n partea de declaraii. Avem:
<def-subprogram> ::= <def-funcie> | <def-procedur>
unde <def-funcie> ::= <antet-funcie> ; <bloc>
<def-procedur> ::= <antet-procedur> ; <bloc>
iar
<antet-funcie> ::= Function <id> [ (l.p.f.) ] : <tipf>
<antet-procedur> ::= Procedure <id> [ (l.p.f.) ]
n aceast sintax <id> este un identicator care constituie numele subprogra-
mului denit. Lista parametrilor formali <l.p.f.> este opional i ea precizeaz
variabilele de care depinde subprogramul i tipul acestor variabile.
Lista parametrilor formali
Lista parametrilor formali este format din mai multe seciuni de parametri separate
ntre ele de caracterul ;. Sintaxa acestei liste este:
<l.p.f.> ::= <spf> { ; <spf> }
unde prin <spf> s-a notat o seciune de parametri formali, seciune care are sintaxa
<spf> ::= <sp-val> | <sp-var> | <pf-funcie> | <pf-procedur>
98 3. Pogramare n limbajul PASCAL
Din punct de vedere sintactic seciunea de parametri valoare <sp-val> este orice
list de identicatori urmat de caracterul : i de un identicator de tip care va
tipul tuturor identicatorilor din lista de identicatori. Deci
<sp-val> ::= <lista-id> : <id-tip>
Seciunea de parametri variabil <sp-var> are sintaxa
<sp-var> ::= Var <lista-id> : <id-tip>
unde <id-tip> este un identicator de tip, denit anterior, deci asemntoare seciunii
parametrilor valoare, singura diferen ind prezena cuvntului Var n faa listei.
Menionm c identicatorii care noteaz parametrii formali nu pot declarai
din nou n partea de declaraii a subprogramului. Ei se consider declarai i pot
folosii n tot subprogramul, ca orice alt variabil local denit n subprogram.
Ca semnicaie, parametri formali noteaz datele de intrare (cele presupuse cunos-
cute) i datele de ieire (rezultate) ale subprogramului. Ei sunt chiar parametrii for-
mali din deniia subalgoritmilor corespunztori.
Variabile locale i variabile globale
n deniia unui subprogram apare la nceput un antet, dup care urmeaz un bloc.
Deci subprogramul are o structur similar unui program. S ne reamintim c un
bloc const din dou pri: o list de declaraii i o instruciune compus. Elementele
denite n lista de declaraii sunt locale pentru blocul n care sunt denite. Acesta
constituie domeniul de vizibilitate al acestor elemente; ele pot folosite numai n
interiorul subprogramului n care au fost declarate, nu i n afara acestuia.
Fie S un subprogram al programului P. Pe lng variabilele locale ale subpro-
gramului S toate elementele declarate n lista de declaraii ale programului P sunt
considerate globale pentru subprogramul S i pot folosite n acest subprogram.
Deci, elementele declarate n S pot folosite numai n S, nu i n restul programului
P. Ele sunt locale pentru S, dar sunt globale i pot folosite n subprogramele S1 i
S2 incluse n S. Elementele denite n P sunt globale i pot folosite n S, S1 i S2.
Considernd programul principal ca un bloc de nivel 0, vom considera subpro-
gramele denite n el ca blocuri de nivel 1. n general, un bloc denit ntr-un bloc de
nivel i are nivelul i + 1.
Dac ntr-un bloc de nivel i se folosete o variabil v i acelai identicator v
noteaz o variabil ntr-un bloc de nivel i+1, cele dou variabile se consider distincte
dei au acelai nume. n acest caz variabila din blocul interior este cea considerat
existent n acest bloc, iar cea exterioar nu exist dect n partea blocului de nivel i
exterioar blocului de nivel i + 1.
Ca exemplu, s considerm programul 3.14.2 din seciunea 3.14. n procedura S1
3.13. Funcii Pascal 99
se folosete variabila local x. Dar i n programul principal se folosete o variabil
global cu numele x. ntruct procedura S1 folosete variabila local cu numele x,
variabila global x i pierde semnicaia n interiorul acestei proceduri (n care exist
o variabil local cu numele x). Cele dou variabile (cu acelai nume x) au rezervate
locaii de memorie distincte i, n consecin, sunt distincte.
3.13 Funcii Pascal
Am vzut c deniia unei funcii const dintr-un antet i dintr-un bloc care va deni
aciunile prin care se calculeaz valoarea funciei. n antet se precizeaz numele
funciei, lista parametrilor formali i tipul funciei, <tipf>. Acesta trebuie s e un
nume de tip referin, sau un tip simplu.
Este necesar ca n instruciunile din corpul <bloc> al funciei s existe cel puin
o atribuire prin care identicatorului <id> s i se atribuie o valoare.
Apelul unei funcii se face scriind ntr-o expresie numele funciei urmat de lista
parametrilor actuali. Trebuie s existe o coresponden biunivoc ntre parametrii
actuali i cei formali folosii n deniia funciei. Dac nu au existat parametri formali
n deniie atunci apelul se face scriind doar numele funciei. Despre corespondena
dintre parametrii formali i parametrii actuali vom vorbi n seciunea 3.14.
3.14 Instruciunea apel de procedur
Apelul unei proceduri se face scriind numele procedurii urmat de lista parametrilor ac-
tuali pe locul unei instruciuni, ceea ce echivaleaz cu execuia tuturor instruciunilor
din bloc.
<apel-procedur> ::= <id> [ (<lista-p.a.> ]
Apelul unei proceduri are ca efect execuia tuturor instruciunilor procedurii
apelate, considernd c ecare parametru formal este egal cu parametrul actual core-
spunztor (a se vedea seciunea 3.12).
Dm un exemplu de program n care se denesc i se apeleaz proceduri. n
plus, programul ilustreaz modul de lucru cu cifrele privite drept caractere, precum
i folosirea funciei ORD.
Se cere s se tipreasc toate numerele ntregi ntlnite ntr-un ir de caractere
care se termin prin caracterul $.
Algoritmul de rezolvare se d n continuare. El folosete un subalgoritm, CIT-
CIFRA(b,c), care citete un caracter c i atribuie lui b valoarea True dac c este o
cifr, respectiv False n caz contrar.
100 3. Pogramare n limbajul PASCAL
Exemplul 3.14.1.
Algoritmul n Pseudocod este urmtorul:
ALGORITMUL CONVERSII ESTE:
REPET
@Caut o cifr; {cu care ncepe un ntreg}
@Calculeaz numrul ntreg format din cifrele consecutive ntlnite;
@Tiprete numrul gsit;
PNCND c=$ SFREP
SFALGORITM
Programul Pascal corespunztor se d n continuare.
Program CONVERSII; { Conversii de secvente de cifre in intregi}
Var c: Char;
nr: Integer;
b: Boolean;
Procedure CITCIFRA(Var b: Boolean; {b=True daca c este}
Var c: Char); {cifra; c=caracterul citit}
Begin
Read(c); b:= True;
If (c<0) Or (c>9) Then
b := False;
End;
Begin {Programul principal}
Repeat
CITCIFRA(b, c);
While Not(b) And (c<>$) Do
CITCIFRA(b, c);
If c <> $ Then
Begin
nr := 0;
Repeat nr := nr*10 + Ord(c) - Ord(0);
CITCIFRA(b, c);
Until Not(b);
Writeln(nr. citit = , nr)
End
Until c=$
End.
3.14. Instruciunea apel de procedur 101
Corespondena dintre parametri actuali i formali
Apelul unui subprogram se face scriind numele acestuia urmat de lista parametrilor
actuali. ntre parametrii din lista parametrilor actuali i parametrii din lista
parametrilor formali trebuie s existe o coresponden biunivoc, iar parametrii care
sunt n coresponden trebuie s aib acelai tip. De fapt, ei trebuie s aib aceeai
semnicaie, s se refere la acelai obiect, s reprezinte aceeai structur de date.
Sintactic un parametru actual poate o expresie Pascal, o variabil, un identi-
cator de procedur sau un identicator de funcie.
Parametri valoare
Parametrul actual corespunztor unui parametru formal valoare f poate orice ex-
presie Pascal e de acelai tip cu parametrul f. La apelul subprogramului se calculeaz
valoarea expresiei e i se atribuie valoarea obinut parametrului formal f. Mai e-
xact, parametrul formal f de tip valoare are rezervat o locaie de memorie n care se
depune valoarea expresiei e nainte de a ncepe execuia instruciunilor subprogramu-
lui. n continuare aceast variabil f este considerat variabil local n subprogram.
Ea i poate schimba valoarea dar aceast valoare nu poate transmis n unitatea
de program n care s-a fcut apelul.
Menionm c este posibil ca elementele fi e s nu aib acelai tip. Excepiile
sunt cele permise de atribuirea f := e.
De asemenea, menionm c parametrii formali de tip valoare corespund vari-
abilelor care se consider cunoscute la intrarea n subalgoritm (datelor de intrare).
Prezentm n continuare un program n care se poate vedea un exemplu de apel
al unui subprogram cu parametri valoare.
Exemplul 3.14.2.
Program Parval; { Parametri formali }
Var x, z : Integer; { de tip valoare i variabila }
Procedure S1(y : Integer);
Var x: Integer;
Begin
x := y y;
y := x;
z := y 4;
Writeln(In procedura y, z =

, y : 5, z : 5);
End; {S1}
Begin
102 3. Pogramare n limbajul PASCAL
For x := 2 To 4 Do
Begin
S1(x);
Writeln(In program x, z =

, x : 5, z : 5);
End
End.
La execuia acestui program se obin urmtoarele rezultate:
In procedura y, z = 4 0
In program x, z = 2 0
In procedura y, z = 9 5
In program x, z = 3 5
In procedura y, z = 16 11
In program x, z = 4 11
Se poate observa c valorile variabilei locale y nu au fost retransmise n programul
principal, parametrul actual x nemodicndu-i valorile prin execuia procedurii S1.
Parametrii de tip referin
Parametri de tip referin se folosesc pentru a transmite valori ntre unitatea apelant
i subprogramul apelat, n ambele sensuri. De obicei, sunt folosii pentru a nota rezul-
tatele obinute n subprogram. Parametrul actual a corespunztor unui parametru
formal de tip referin f este obligatoriu o variabil de acelai tip cu parametrul formal
f. La apelul unui subprogram parametrul formal se consider identic cu parametrul
actual corespunztor. Practic, acest lucru se realizeaz prin faptul c amndoi au
aceeai adres n memorie. Astfel, parametrul actual a devine parametru global;
orice modicare a parametrului formal f este i o modicare a parametrului actual a.
Se recomand ca parametrii actuali corespunztori parametrilor formali variabil
s e distinci. Unele implementri consider eroare cnd la doi parametri formali
corespunde acelai parametru actual, altele accept o astfel de coresponden. Atenie
ns la o asemenea situaie ntruct ind identici cu acelai parametru actual, cei doi
parametri formali devin identici ntre ei, ceea ce poate duce la efecte neateptate. De
aceea, recomandm s se evite o asemenea utilizare, chiar dac ea este permis.
Parametrii funcie i parametrii procedur
Din deniia sintactic a listei parametrilor formali se observ c un parametru formal
poate i o funcie sau o procedur. Parametrul actual trebuie s e o funcie,
respectiv o procedur similar parametrului formal corespunztor.
3.14. Instruciunea apel de procedur 103
Un exemplu de program n care se folosesc parametrii formali i actuali funcii i
proceduri este cel de mai jos, n care se calculeaz radicalii de ordinul doi i trei din
constanta mm (n program egal cu 2) rezolvnd ecuaiile:
x
2
- mm = 0, notat g(x) = 0,
respectiv
x
3
- mm = 0, notat h(x) = 0.
Pentru rezolvarea unei ecuaii se pot folosi mai multe metode. n program am ales
dou: metoda njumtirii i metoda coardei. ntruct metoda coardei folosete i
prima derivat, am notat prin f1, respectiv g1 derivatele funciilor f i g.
Exemplul n Pseudocod, a fost prezentat n seciunea 1.4.
Exemplul 3.14.3.
Program lpf; { P.F. funcii si proceduri}
Const mm = 2;
Type
fct = Function (x: real): Real;
sub1 = Procedure (a, b: Real; Var r:Real; f,f1:fct);
Var r: Real;
i: Integer;
Function g(s: Real): Real;
Begin
g := s*s - mm;
End;
Function h(s: real): Real;
Begin
h:= s*s*s - mm;
End;
Function g1(s: real): Real;
Begin
g1 := s + s;
End;
Function h1(s: Real): Real;
Begin
h1 := 3*s*s;
End;
Procedure coarda(a, b: Real; Var r: Real; f, f1: fct); {Se rezolva ecuatia
104 3. Pogramare n limbajul PASCAL
f(x) = 0 prin metoda coardei}
Var c, t: Real;
Begin
c := a; t := b;
Repeat
c := c - f(c)*(t-c)/(f(t)-f(c));
t := t - f(t)/f1(t);
Until t - c < 0.00001;
r := (c+t)/2
End;
Procedure juma(a, b: Real; Var r: Real; f, f1: fct); {Se rezolva ecuatia
f(x)=0 prin metoda injumatatirii}
Begin
Repeat
r := (a+b)/2;
If f(a)*f(r) < 0 Then
b := r
Else
a := r;
Until b - a < 0.00001
End;
Procedure Rezec(a, b: Real; Var r: Real; f, f1: fct; met: sub1);
Begin
met(a, b, r, f, f1);
End;
Begin
Eriteln(injumatatire coarda: );
Writeln(radical din 2);
Rezec(1, 2, r, g, g1, juma);
Write(r = , r:9:5);
Rezec(1, 2, r, g, g1, coarda);
Writeln( , r:9:5);
Writeln(radical din 3);
Rezec(1, 2, r, h, h1, juma);
Write(r = , r:9:5);
Rezec(1, 2, r, h, h1, coarda);
3.15. Apel recursiv 105
Writeln( , r:9:5);
End.
3.15 Apel recursiv
n exemplele date se observ c apelul unui subprogram se face dup ce el a fost
denit. Este ns permis ca n interiorul unei proceduri s e denit o alt procedur.
Aceast procedur poate utilizat numai n interiorul procedurii n care a fost
declarat i numai dup ce a fost denit.
Este posibil, ca un subprogram s se apeleze pe el nsui, recursiv. Ca exemplu,
prezentm n continuare un program care folosete o funcie care calculeaz recursiv
valoarea n! cu ajutorul formulei n! = n.(n 1)!.
Exemplul 3.15.1.
Program ApelRecursiv; { n Factorial }
Type nat = 0..maxint;
Var i: nat;
Function Fact(n: nat): nat;
Begin
If n = 0 Then
Fact := 1
Else
Fact := n * Fact(n-1)
End;
Begin
For i:=3 to 7 do
Writeln(i, ! = , Fact(i))
End.
S urmrim execuia apelului FACT(n) pentru n = 3. S observm c funcia
Fact nu are nici o variabil local n afar de parametrul formal de valoare n. Deci,
la apelul acestei funcii se vor rezerva dou locaii de memorie, una pentru n i una
pentru valoarea funciei FACT, ecare apel nsemnnd o astfel de rezervare.
Deci, dup primul apel, zona de memorie alocat este cea situaia a) de mai jos.
Pentru a efectua atribuirea Fact(1) := 3*Fact(2) se apeleaz Fact(2) i se rezerv
din nou dou locaii de memorie, ajungnd la situaia din situaia b) de mai jos.
La execuia acestui apel trebuie efectuat atribuirea Fact(2) := 2*Fact(1). Deci are
106 3. Pogramare n limbajul PASCAL
loc un al treilea apel, Fact(1), pentru care se rezerv din nou memorie, ajungndu-
se la situaia c) de mai jos. De aceast dat se cere efectuarea atribuirii Fact(3) :=
1*Fact(0) i are loc un al patrulea apel, Fact(0), ajungndu-se la situaia d) de mai jos.
Cnd ultimul apel s-a executat, el ntoarce valoarea Fact(4) := 1 i se elibereaz zona
de memorie corespunztoare ajungndu-se la situaia situaia e) de mai jos. ntruct
i apelul Fact(1) a fost executat, se ajunge la situaia f) de mai jos. Se efectueaz
i atribuirea Fact(2) := 2*Fact(1) = 2 cu care se termin execuia apelului Fact(2),
ajungndu-se la situaia g) de mai jos. n aceast situaie se ncheie i execuia
primului apel cu valoarea Fact(1) := 6.
3 ?
n Fact1
a) 3 ? 2 ?
n Fact1 n Fact2
b) 3 ? 2 ? 1 ?
n Fact1 n Fact2 n" Fact3
c) 3 ? 2 ? 1 ? 0 1
n Fact1 n Fact2 n" Fact3 n" Fact4
d) 3 ? 2 ? 1 1
n Fact1 n Fact2 n" Fact3
e) 3 ? 2 2
n Fact1 n Fact2
f) 3 6
n Fact1
g)
S observm att modul de execuie al unui apel recursiv ct i faptul c necesarul
de memorie crete la ecare apel. Iar n cazul n care zona de date locale ale procedurii
este mare, volumul de memorie utilizat poate crete foarte mult.
Din aceast cauz apelul recursiv nu este indicat. Consumul de memorie i timpul
necesar execuiei sunt mult mai mari dect n cazul unui program nerecursiv core-
spunztor aceleai probleme. Totui, folosirea procedurilor recursive are avantajul
unei descrieri mai clare i mai apropiat de limbajul matematic.
3.16 Tipuri de date structurate
Am vzut c prin termenul de dat nelegem o valoare a unei informaii folosit
ntr-un algoritm, cum ar numrul 1394, sau caracterul A, sau (1, Martie, 1996).
O dat atomic este o dat pe care o putem considera, cel puin pentru un moment,
3.16. Tipuri de date structurate 107
o entitate nedecompozabil. De exemplu, numrul 1394 poate considerat o dat
atomic memorat, scris pe aceast hrtie. Dar, putem vedea acest ntreg i ca o
dat compus, ca o secven de cifre scrise aici de la stnga spre dreapta; n acest caz
ecare cifr este considerat atomic, ns ntregul va o dat compus. O cifr la
rndul ei ar putea considerat compus, de exemplu, din puncte. Astfel putem alege
orice nivel la care s oprim descompunerea unei date, considernd-o apoi atomic.
Dac descompunem o dat, ca i mai sus ntregul 1394, atunci valorile obinute
le vom numi elemente componente, sau simplu elemente. O dat care se compune
din mai multe elemente o numim dat structurat. O dat structurat are elemente
componente i o structur, care denete modul de aranjare sau relaiile ce se pot
stabili ntre elemente.
n ncercarea de a grupa datele dup caracteristici comune a fost introdus noi-
unea de tip. Printr-un tip de date nelegem o mulime de valori (de date) i o mulime
de operaii ntre aceste valori. Dac valorile din mulime sunt atomice atunci avem
un tip de date atomic, iar dac valorile sunt structurate atunci avem un tip de date
structurat, sau o structur de date. Deci o structur de date este un tip de date ale
crui valori:
(1) pot descompuse ntr-o mulime de elemente de date, ecare element putnd
atomic sau o alt structur de date;
(2) includ o mulime de asocieri, sau relaii (structura) ntre elementele componente.
Operaiile unui tip de date structurat pot s acioneze nu numai asupra valorilor
tipului de date ci i asupra elementelor componente ale structurii de date.
Alegerea unei reprezentri potrivite pentru obiectele de date pe care le folosim
ntr-un program este de importan major. Dar, s denim nti ce nelegem prin
reprezentarea datelor. Termenul reprezentarea datelor nseamn o alegere particular,
din mai multe care sunt posibile, a componentelor, a tipului lor, i a organizrii acestor
valori memorate ntr-un obiect.
n acest capitol sunt prezentate cteva alternative disponibile n limbajul Pascal
pentru reprezentarea datelor structurate.
1. Structura de tablou
Una din structurile de date eseniale n programare sunt cele de tip tablou. Cel mai
simplu mod de a folosi tablourile este de a reprezenta date organizate ca i un ir
elemente. La fel, cu ajutorul lor se pot reprezenta diferite tipuri de tablouri. De
exemplu, un tabel al notelor obinute la un examen de studenii dintr-o grup, ar
putea arta astfel
108 3. Pogramare n limbajul PASCAL
Student Nota
1 9
2 7
3 10
. . . . . .
25 8
Un astfel de tabel ar putea reprezentat ntr-un program printr-un tablou.
Un tablou const dintr-un ir elemente, ecare element ind identicat printr-un
indice. Elementele sunt toate de acelai tip de date, care poate orice tip. Indicii
sunt dintr-un subdomeniu al unui tip ordinal. Caracteristicile eseniale ale unui tablou
sunt dou: elementele sunt ordonate prin irul valorilor indicilor, respectiv elementele
sunt de acelai tip.
Pentru a deni reprezentarea unui tablou trebuie s precizm dou lucruri: sub-
domeniul indicilor i tipul de date al elementelor componente. Sintaxa specicrii n
Pascal a unei structuri de tablou este
<tablou> ::= Array [<tip1>] of <tip2>
unde parantezele drepte i tipurile <tip1> i <tip2> sunt obligatorii. Tipul <tip1>
se numete tip de indexare i precizeaz valorile pe care le poate lua indicele tabloului.
El poate orice tip ordinal diferit de Integer, putnd ns un subdomeniu al tipului
Integer. Tipul elementelor tabloului este <tip2>, care poate orice tip denit
anterior: predenit sau denit de ctre utilizator, sau orice tip anonim.
Astfel, prin array [1...25] of integer
se specic un tip de tablou cu componente ntregi, ale crui elemente sunt indexate
prin numere ntregi de la 1 la 25.
Prin Array[A..Z] Of Real
se specic o structur de tablou cu componente reale ale crui elemente sunt indexate
prin caractere aate n subdomeniul A...Z. Dac tabloul Tab are acest tip atunci
elementele sale sunt Tab[c] pentru c n subdomeniul A...Z.
Un element al tabloului se refer prin scrierea numelui tabloului urmat de rangul
elementului n acest tablou (indicele) scris ntre parantezele drepte, [ i ]. Un element
selectat al tabloului poate folosit ca i orice variabil de tipul elementelor tabloului.
Singura operaie predenit asupra tablourilor este atribuirea, A := B, care are
ca efect copierea valorilor elementelor tabloului B n elementele corespunztoare
tabloului A. Cele dou tablouri trebuie s e de acelai tip.
Un tablou este reprezentat n memoria calculatorului ca i un ir de locaii de me-
morare, ecrui element corespunzndu-i o locaie. Tabloul Pascal este o abstractizare
3.16. Tipuri de date structurate 109
care ascunde detaliile despre cum este organizat un tablou n memoria calculatorului.
n gura urmtoare este sugerat reprezentarea unui tablou n memorie, ecrei locaii
de memorare corespunzndu-i un dreptunghi, valoarea unui element ind nscris n
dreptunghiul corespunztor. S notm c indicii nu sunt memorai ca i parte a
tabloului.
Nota[1] Nota[2] Nota[3] . . . Nota[25]
9 7 10 . . . 8
Elementele unui tablou pot la rndul lor tablouri. Astfel, elementele unui tablou
de tipul
Array[1..10] Of Array[1..6] Of Real
sunt vectori cu 6 componente reale. Dac T este un tablou de acest tip atunci T are
10 componente, ecare component ind un vector cu 6 componente. De fapt este
vorba de o matrice cu 10 linii i 6 coloane. Componenta T[i] a acestui tablou va un
vector cu 6 componente numere reale. Selectarea elementului cu indicele j al tabloului
T[i] poate fcut prin T[i][j].
Menionm c se accept o prescurtare a declaraiei de mai sus sub forma
Array[1..10, 1..6] Of Real
Dei nu este o declaraie echivalent cu cea de mai nainte, ea permite totui declararea
unei matrice cu 10 linii i 6 coloane. Diferena const n faptul c folosind aceast
declaraie o linie a matricei nu mai este considerat ca o entitate de sine stttoare.
Referirea la linia i prin T[i] este greit n acest caz, iar prin T[i, j] se refer elementul
din linia i coloana j.
n continuare, vom scrie un program n care se folosete un subprogram pentru
ordonarea cresctoare a unui ir de numere reale, pe care-l vom apela pentru a ordona
mai nti un ir dat de numere reale x[1], x[2], ..., x[n], iar apoi pentru a ordona
ptratele acestor numere.
Exemplul 3.16.1.
Program Tablou1; { Tablouri}
Type Vector = array[1..100] Of Real;
Var i, n: Integer;
x : Vector;
Procedure Tipar(n:Integer; x:vector); {Tipareste, vectorul X cu n elemente}
Begin
Writeln;
For i:=1 To n Do Write(x[i])
End; {Tipar}
110 3. Pogramare n limbajul PASCAL
Procedure Ordonare(n: Integer; var X: Vector); {Ordoneaz nedescrescator }
{ primele n componente ale vectorului X}
Var i, kod: Integer;
t: Real;
Begin
Repeat kod := 0;
For i:=1 To n-1 Do
If x[i] > x[i+1] Then
Begin
kod := 1; t := x[i];
x[i] := x[i+1];
x[i+1] := t
End {if}
Until kod = 0
End; {Ordonare}
Begin
Write(n = ); Readln(n);
For i:=1 To n Do
Read(x[i]);
Writeln(Sirul ordonat este:);
Ordonare(n, X);
Tipar;
For i:=1 To n Do
x[i] := x[i]*x[i];
Writeln(Sirul patratelor dupa ordonare:);
Ordonare(n, X);
Tipar(n,X)
End.
Dm i un exemplu de program n care apar matrici. Programul rezolv urm-
toarea problem:
Exemplul 3.16.2. Se d o matrice patrat A i se cere s se tipreasc matricele
A, A
2
, A
3
i A
4
. Pentru tiprirea unei matrice i pentru nmulirea a dou matrice se
folosesc procedurile TipMat, respectiv ProdMat. Programul Pascal este urmtorul:
Program PuteriMat; { Puterile unei matrice}
Const n = 5;
Type Mat = Array[1..n, 1..n] Of Real;
Var A, B, C: Mat;
3.16. Tipuri de date structurate 111
Procedure CitMat(n: Byte; var A: Mat); {Citeste matricea A}
Var i, j: Byte; {patrata de ordinul n}
Begin
For i:=1 To n Do
For j:=1 To n Do
Begin
Write(A(, i, ,, j, )=);
Readln(A[i,j])
End;
End;
Procedure TipMat(n: Integer; {Tiparete mesajul s si}
A: Mat; s: String); {matricea A de ordinul n}
Var i, j: Integer;
Begin
Writeln; Writeln;
Writeln(s);
For i:=1 To n Do
Begin
Writeln;
For j:=1 To n Do
Write(A[i,j]:8:1);
End
End; {TipMat}
Procedure ProdMat(n: Byte; A, B: Mat; var C: Mat); {n = ordinul matricelor}
{C := A * B}
Var i, j, k: Integer;
s : Real;
Begin
For i:=1 To n Do
For j:=1 To n Do
Begin
s:=0;
For k:=1 To n Do
s := s+A[i,k]*B[k,j];
C[i,j] := s
End
End; {ProdMat}
112 3. Pogramare n limbajul PASCAL
Begin
Writeln(Se tiparesc puterile unei matrice);
Writeln(Dati matricea !);
CitMat(n, A);
TipMat(n, A, Matricea A este: );
ProdMat(n, A, A, B);
TipMat(n, B, Matricea A*A este: );
ProdMat(n, A, B, C);
TipMat(n, C, Matricea A*A*A este: );
ProdMat(n, B, B, C);
TipMat(n, C, Matricea A*A*A*A este:);
End.
Structura de date nregistrare
Multe obiecte din lumea real le descriem de obicei prin enumerarea unor atribute
importante pe care le au. Atributele servesc la descrierea clasei generale de obiecte -
tipul obiectului. Un obiect particular de acel tip este denit prin asocierea unei valori
particulare ecrui atribut. De exemplu, o noti dintr-o agend telefonic personal
poate referi o persoan prin atributele Nume, Telefon i Adres, iar o persoan notat
n agend ar putea :
Ioana Pop; 174563; G. Enescu, 25/A.
n programare putem descrie date compuse (deci i tipul de date corespunztor)
ntr-un mod asemntor. Precizarea (denirea) tipului de date se va face prin enu-
merarea numelor unor atribute i precizarea unui tip de date asociat ecrui atribut.
Un obiect particular de acest tip nou va conine o valoare particular pentru ecare
atribut specicat. Un astfel de tip de date l vom numi tip de date nregistrare.
Fiecare atribut l numim cmp al nregistrrii. Un obiect de date de tip nregistrare
va numit o nregistrare.
Observm c structura de date nregistrare modeleaz produsul cartezian din
matematic. O nregistrare const dintr-un numr x de elemente componente de
diferite tipuri. Caracteristica esenial a unei nregistrri este c ea grupeaz ele-
mente de dat de diferite tipuri ntr-o singur entitate. Acest aspect contribuie la o
exprimare concis i uor de urmrit n programare.
Sintaxa specicrii unui tip nregistrare n limbajul Pascal este:
Record <selector> : <tip> { ; <selector> : <tip> } End
3.16. Tipuri de date structurate 113
unde <selector> este un identicator sau o list de identicatori iar <tip> este un tip
predenit sau denit anterior i specic tipul selectorului din stnga sa. Selectorii
care apar dup cuvntul record trebuie s e distinci ntre ei i constituie numele dat
componentelor corespunztoare ale produsului cartezian.
Un astfel de tip nregistrare poate primi un nume folosind declaraia type, prezen-
tat anterior. De exemplu, prin
Type Data = Record
zi : 1..31;
luna: 1..12;
an : 1900..1999
End;
se denete un tip nregistrare cu numele Data i care are trei componente: zi, luna,
an. Se observ c este un tip ce conine toate datele din secolul nostru, sub forma
unor triplete (z,l,a).
Operaiile asupra nregistrrilor sunt atribuirea nregistrrilor i selectarea unui
cmp al unei nregistrri. Dac A i B sunt dou nregistrri de acelai tip, atunci
atribuirea A := B, va avea ca efect copierea valorilor cmpurilor nregistrrii B n
cmpurile nregistrrii A. Pentru selectarea unui cmp particular al unei nregistrri
vom folosi notaia
<variabila-nregistrare> . <selector>
Astfel, pentru variabila V de tipul Data vom avea urmtoarele trei componente
(variabile selectate):
V.zi, V.luna, V.an.
Vom scrie o procedur care rezolv problema de mai jos i care folosete tipul
Data, denit mai sus. Problema este urmtoarea:
Exemplul 3.16.3. S se determine vrsta unei persoane n numr de zile dac se
cunoate data naterii persoanei i data curent. Subalgoritmul pentru determinarea
vrstei, dat sub form de funcie, este urmtorul:
Pseudocod:
FUNCIA VARSTA(Dnas, Dazi) ESTE:
FIE nr := NRZIAN(Dazi);
@Pentru (ecare an ntreg din via) adun la nr
numrul zilelor anului respectiv;
FIE VARSTA := nr - NRZIAN(Dnas);
sf-VARSTA
114 3. Pogramare n limbajul PASCAL
Acest subalgoritm folosete funcia NRZIAN(zi) pentru a determina a cta zi din
an este o dat curent. Funcia menionat este descris n continuare.
FUNCIA NRZIAN(zian) ESTE:
FIE nr := ziua curent a lunii;
DAC@(nu suntem n ianuarie) ATUNCI
PENTRU@ ecare lun ntreag EXECUT
FIE nr := nr + numrul zilelor lunii i;
SFPENTRU
DAC@ (a trecut februarie) ATUNCI
DAC@ anuI este bisect ATUNCI
nr:=nr+1
SFDAC
SFDAC
SFDAC
FIE NRZIAN:=nr;
SF-NRZIAN
Procedura Pascal corespunztoare se denete n programul urmtor:
Program ApelFunctie; { Tipul inregistrare}
Const NZile: Array[1..12] Of Integer =(31, 28, 31, 30, 31, 30, 31, 31, 30, 31,
30, 31);
Type Data = Record
zi : 1..31;
luna: 1..12;
an : 1900..1999
End;
Var Dnas, { Data nasterii }
Dazi: Data; { Data curenta }
Function Bisect(a: Integer): Boolean; { Adevarata daca }
Begin { a e bisect }
If a Mod 4 = 0 Then
Bisect := True
Else
Bisect := False
End;
Procedure CitData(Var D: Data); { Citete un triplet }
Begin { zi, lun, an care }
3.16. Tipuri de date structurate 115
Write(ziua=); Readln(D.zi); { reprezint o dat }
Write(luna=); Readln(D.luna);
Write(anul=); Readln(D.an);
End;
Function NrZiAn(V: Data): Integer; { NRZIAN := a cata zi }
Var i, nr: Integer; { in an este data V }
Begin
nr := V.zi;
If V.luna > 1 Then
For i:=1 To V.Luna-1 Do
nr := nr + NZile[i];
If V.luna > 2 Then
If Bisect(V.an) Then
nr := nr + 1;
NrZiAn := nr
End; {NRZIAN}
Function Varsta(Dnas, Dazi: Data): Integer; { Varsta := }
Var i, nr: Integer; {numarul de zile aate}
Begin {intre datele Dnas si Dazi}
nr := NrZiAn(Dazi);
For i := Dnas.an To Dazi.an-1 Do
Begin
nr:=nr+365;
If Bisect(i) Then
nr:=nr+1
End; {For}
Varsta := nr - NrZiAn(Dnas);
End; {Varsta}
Begin {Programul principal}
Writeln(Dati data nasterii: ); CitData(Dnas);
Writeln(Dati data curenta: ); CitData(Dazi);
Writeln(Persoana nascuta in: );
Writeln((, Dnas.zi, ,, Dnas.luna, ,, Dnas.an, ));
Writeln(are varsta , Varsta(Dnas,Dazi), zile.);
End.
116 3. Pogramare n limbajul PASCAL
n denirea unui tip nregistrare o component poate la rndul ei de tipul nre-
gistrare. Un astfel de exemplu se d n continuare:
Type Student = Record
nume, prenume: Array[1..8] Of Char ;
datan: record
zi : 1..31 ;
luna: 1..12 ;
an : 1900..1989
End;
note: Array[1..12] Of 1..10
End;
n acest caz, dac X are tipul Student atunci prin X.datan se noteaz tripletul
X.datan.zi X.datan.luna X.datan.an
care reprezint data naterii studentului X, iar X.nume este numele acestui student.
3.17 Tipul referin
n multe aplicaii practice care folosesc prelucrri de date, nu este posibil s cunoatem
a priori dimensiunea datelor. Din aceast cauz, utilizarea unui tablou pentru a stoca
aceste date este inecient, deoarece e facem risip de memorie printr-o alocare
static acoperitoare, e sub dimensionm tabloul pentru stocarea datelor, ceea ce
poate duce la fenomene de depire a zonei de memorie alocat datelor, acest fenomen
ind un fenomen sever care poate duce la blocarea execuiei programului i chiar
la blocarea sistemului de calcul. Limbajul de programare Turbo Pascal stabilete
dimensiunea de memorie alocat datelor de la nivelul codului surs, care, compilat
i editat, se transform n cod executabil. Pe parcursul execuiei nu se pot modica
dinamic alocrile de date declarate la nivelul codului surs.
De aceea, pentru a rezolva problema unei alocri dinamice a memoriei trebuie
s utilizm un tip de dat special, numit tip referin sau pointer i o serie de
proceduri speciale care s aloce memorie sau s elibereze zona de memorie folosit i
care nu mai este necesar. Tipul de date referin (pointer) va conine adresa unui
anumit tip de dat. Declaraia de tip este:
nume_dat = tip;
unde nume_dat este numele noului tip de dat referin, iar tip reprezint tipul
datelor referite de ctre datele de tip nume_dat.
3.17. Tipul referin 117
Declaraia de mai sus este o declaraie generic de tip, neavnd ca efect rezervarea
propriu-zis de memorie.
Pentru a realiza efectiv alocarea unei zone de memorie de dimensiunea dat de
tipul de dat tip, va trebui s folosim procedura New. Apelul procedurii se face
astfel:
New(variabil _referin);
Unde variabil_referin este o variabil numit variabil dinamic [Cri, 1992].
Procedura New realizeaz alocarea dinamic a memoriei heap pe parcursul exe-
cuiei programului. n urma apelrii procedurii New, variabilei dinamice vari-
abil_referin i se va atribui o adres de memorie de dimensiune egal cu zona
de memorie ocupat de o dat de tipul referit. Asupra variabilelor dinamice pot
efectuate orice operaii permise de tipul acestora. Variabilele dinamice pot primi
valori i prin operaii de atribuire, pot apare n expresii relaionale care utilizeaz
operatorii relaionali = i <>.
Limbajul Turbo Pascal permite utilizarea tipului pre-denit pointer. Acest tip de
dat este compatibil cu orice tip referin denit de utilizator. Unei variabile de tip
pointer i poate atribuit valoarea adresei oricrei variabile, proceduri sau funcii
denite de utilizator. O astfel de adres poate obinut prin utilizarea operatorului
@, astfel:
@variabil;
Dac o variabil de referin are valoarea Nil nseamn c variabila respectiv conine
o adres imposibil, care nu exist n zona de memorie. Eliberarea efectiv a spaiului
de memorie ocupat se face cu ajutorul procedurii DISPOSE, dup urmtoarea regul:
Dispose(variabil_referin);
unde adresa zonei de memorie ce se va elibera este coninut n variabil_referin.
Dimensiunea zonei de memorie eliberat este dat de dimensiunea tipului de dat
referit de variabil_referin.
Dac dorim s alocm sau s eliberm n mod explicit un anumit numr de octei
putem folosi procedurile GetMeM i FreeMem.
118 3. Pogramare n limbajul PASCAL
3.18 Probleme propuse
1. Se d un ir de numere naturale al crui sfrit este marcat prin valoarea 0.
Spunem c dou numere naturale sunt asemenea dac scrierile lor n baza 10 se
face cu aceleai cifre (Ex. 36668 i 8363). S se gseasc secvena de numere
consecutive asemenea de lungime maxim din irul dat i frecvenele cifrelor n
scrierea numerelor date.
2. Se citesc mai multe iruri de numere naturale nenule ecare ir terminndu-se
la citirea valorii zero. Pentru ecare ir s se tipreasc secvena de elemente
consecutive de lungime maxim format din numere prime. La sfrit se vor
tipri i toate numerele prime ntlnite. Citirea se va ncheia cnd irul citit are
0 termeni (altfel spus la citirea a doi de zero consecutivi)
3. S se scrie un program pentru determinarea reuniunii unor mulimi de numere
ntregi pozitive. O mulime se d ntotdeauna ncepnd pe un rnd nou, iar
sfritul elementelor sale este marcat prin numrul 0. Mulimile se termin la
ntlnirea mulimii vide. Se va tipri reuniunea acestor mulimi i mulimea cu
cele mai multe elemente, tiprirea elementelor unei mulimi se va face n ordinea
cresctoare a valorilor elementelor.
4. Fiind date mai multe polinoame cu coecieni reali s se determine suma lor i
polinomul de grad maxim. Un polinom se d e prin monoamele sale, e prin
grad i coecieni. Citirea polinoamelor se va ncheia la introducerea gradului
negativ.
5. Participanii la un concurs sunt identicai printr-un numr strict pozitiv
(numr legitimaie), i obin un punctaj (numr ntreg). S se scrie un program
Pascal care citete rezultatele obinute la acest examen i tiprete toi candi-
daii ordonai cresctor dup numrul legitimaiilor, cu punctajul corespunztor
i primii m (m > 0) candidai n ordinea descresctoare a punctajelor (dac doi
dintre acetia au punctaje egale atunci ei se difereniaz n ordine cresctoare
dup numrul legitimaiei).
6. S se scrie un program care citete cte un polinom cu coecieni ntregi (in-
trodus e prin grad i coecieni e prin monoamele sale), pn la ntlnirea
unui polinom de grad 0. Pentru ecare polinom P citit, determin rdcinile
naturale ale lui P i le tiprete sub forma:
Rdcinile naturale ale polinomului P cu coecienii
. . .
3.18. Probleme propuse 119
sunt ...
7. Se dau un polinom P (grad + irul coecienilor), i un ir de triplete (a, b, e)
pentru care P(a) P(b) <= 0 si e > 0, irul terminndu-se cu un triplet n
care e < 0. S se gseasc rdcina ecuaiei P(x) = 0 din intervalul [a, b], prin
metoda njumtirii, cu eroarea e, i s se tipreasc:
"n intervalul [a, b] polinomul are rdcina ..., aproximat cu precizia ...(valoarea
lui e)".
pentru ecare triplet, iar la sfrit s se tipreasc toate rdcinile pozitive
gsite.
8. S se scrie un program care creeaz matricea ptratic de ordinul n (dat),
format din scrierea cifrelor semnicative ale numerelor naturale n ordinea
liniilor i tiprete matricele A, A
2
, ..., A
m
.
9. Fiind date dou numere naturale s se scrie un program Pascal pentru a deter-
mina cel mai mic i cel mai mare dintre ele. Un numr poate avea cel mult 100
cifre. Numerele se introduc de la tastatur prin cifrele lor (reprezentare n baza
10).
10. S se scrie un program Pascal care citete mai multe matrice i tiprete matricea
care are determinantul cel mai mare. Pentru ecare matrice programul citete
ordinul matricei i elementele n ordinea liniilor. Execuia programului se ncheie
cnd se introduce 0 pentru ordinul unei matrice.
11. S se scrie un program care citete dou numere naturale nenule a i b si tiprete
restul mpririi lui a la b. Numerele pot avea cel mult 50 cifre i sunt reprezen-
tate n baza 10.
12. S se scrie un program care tiprete rdcinile raionale ale unui polinom cu
coecieni ntregi (dac exist), polinom dat prin grad i coecienii si.
120 3. Pogramare n limbajul PASCAL
Capitolul 4
Structuri de date
4.1 Lista liniar simplu nlnuit
Multe din informaiile prelucrate de calculator sunt organizate ca liste: elementele
unui vector, irul format de numele din cartea de telefon (lista abonailor), lista
candidailor la admitere ntr-o facultate, lista materialelor necesare dintr-o secie in-
dustrial, lista locatarilor unui imobil. De aceea, lista ocup un loc important ntre
structurile de date uzuale. n cele ce urmeaz, prezentm cteva elemente de baz
referitoare la liste, modalitile de reprezentare a listelor n calculator i unele aplicaii
semnicative.
4.1.1 Deniii
Prin list nelegem un ir (eventual vid) de elemente aparinnd unei mulimi de
date [Tom, 1997]. Memorarea listelor liniare se poate face n mai multe moduri, n
continuare prezentndu-se unele dintre ele.
Alocarea secvenial (static) const n a memora elementele listei n locaii
succesive de memorie, conform ordinii acestor elemente n list; n acelai timp se
memoreaz adresa de baz (adresa primului element al listei). Un exemplu tipic
este cel n care elementele listei sunt memorate ntr-un vector, adresa de baz ind
adresa primului element al vectorului.
Alocarea nlnuit (dinamic) presupune c ecare element al listei liniare
este nlocuit cu o celul format din dou pri: o parte conine o informaie
specic al elementului i o parte cu informaia de legtur, care conine adresa
celulei corespunztor urmtorului element.
121
122 4. Structuri de date
succesor info
nod
Figura 4.1: Structura unui nod al listei simplu nlnuite
Ca i la alocarea secvenial, mai trebuie memorat o adres de baz; n plus,
partea de legtur a ultimei celule primete o valoare ce nu poate desemna o legtur.
Utilizm forma de alocare dinamic, ceea ce nseamn c n timpul rulrii progra-
mului, n funcie de necesiti, se aloc memorie suplimentar sau se renun la ea.
Pentru alocarea dinamic utilizm tipul de date referin (seciunea 3.17). Se con-
sider secvena de program cu implementarea elementelor, element oarecare al listei
care este format din informaia util (info) i un pointer care se refer la urmtorul
element al listei :
O list liniar simplu nlnuit este o structur de forma:
adr3 inf2 adr2 inf1
adr2
. . .
NIL inf
adrn
LIST
Figura 4.2: Structura unei liste simplu nlnuite
unde semnicaia notaiilor folosite este urmtoarea:
adr1, adr2, ..., adrn reprezint adresele din memorie ale celor n nregistrri;
inf1, inf2, ..., infn reprezint informaiile utile din cele n nregistrri
Implementarea unui element al acestei structuri se face n felul urmtor n limbajul
Pascal:
Type
adresa = nod ;
nod=Record
info : tip ;
succesor : adresa ;
end;
Var
List : adresa ;
4.1. Lista liniar simplu nlnuit 123
Numele de "list simplu nlnuit" provine din faptul c ecare element al listei
conine o singur adres i anume adresa elementului urmtor din list. Aici avem
o excepie pentru ultimul element, care are cmpul de adres cuvntul cheie NIL
(semnicnd "nici o adresa").
4.1.2 Operaii specice listei
Coninutul listei se poate modica prin urmtoarele operaii:
a. iniializarea unei liste ca o list vid;
b. inserarea de noi elemente n orice loc din list;
c. cutarea unor elemente n orice poziie din list;
d. tergerea unor elemente din orice poziie a listei;
e. modicarea unui element dintr-o poziie dat;
Alte operaii sunt cele de caracterizare. Acestea nu modic structura listelor,
ci furnizez informaii despre ele. Dintre operaiile de caracterizare vom considera n
continuare:
determinarea lungimii listei ( numrul de elemente ) ;
localizarea elementului din list care ndeplinete o anumit condiie ;
a. Algoritmul Creare (Iniializare)
Operaia realizeaz iniializarea listei ca o list vid, adic o list fr elemente:
Procedure Creare
List = NIL;
End;
b. Algoritmul Inserare
b1. Inserare_nceput : inserm un element la nceputul listei;
- alocarea de spaiu elementului nou;
- modicare de legturi ( a i b );
Procedure Inserare_nceput ( List , info_nou )
Begin
new(adr);
adr.succesor : = List;
124 4. Structuri de date
adr
b
a
adr2 inf1
adr1
inf1 adr1
List
. . .
NIL inf
adrn
Figura 4.3: Operaia de inserare la nceputul unei liste simplu nlnuite
List : = adr;
adr.info : = info_nou;
end.
b2. Inserare_Sfrit : inserm un element la sfritul listei ;
adr ultim
b
a
adrn
infn NIL inf_nou NIL
a no dr_
inf1
u
adr2
adr1
List
. . .
Figura 4.4: Operaia de inserare la sfritul unei liste simplu nlnuite
Secvena de operaii necesar:
- gsirea adresei ultimului element;
- alocarea spaiului elementului nou;
- a ( ultimul devine penultimul);
- b ( noul element devine ultimul);
- introducerea de informaii;
Procedure Inserare_Sfrit ( List, info_nou )
Var
ultim : adresa;
Begin
ultim = List;
While ultim.succesor <> NIL Do
ultim : = ultim.succesor;
New (adr);
ultim. succesor : = adr;
4.1. Lista liniar simplu nlnuit 125
adr.succesor : = NIL;
adr.info : = info_nou;
end;
b3. Inserare_Mijloc inserm un element nou dup un element dat din list, a crui
adres este numit dup;
adr
b
dup
a
inf_nou succesor
. . . . . .
Figura 4.5: Operaia de inserare n interiorul unei liste simplu nlnuite
Secvena de operaii necesar:
- alocare de spaiu ;
- succesorul noului element devine elementul listei ( a. );
- succesorul elementului dup devine noul element ( b. ) ;
- introducem informaia nou ;
Procedure Inserare_Interior ( List , dup , info_nou )
Begin
New(adr);
adr.succesor : = dup.succesor;
dup.succesor : = adr;
adr.info : = info_nou;
End;
c. Algoritmul cutare
Algoritmul caut n lista simplu nlnuit nodul care conine informaia info_cutat.
Dac ea exist, funcia de cutare va returna adresa nodului ce conine informaia
cutat. Dac informaia nu exist, atunci funcia va returna o adres vid (NIL).
126 4. Structuri de date
Function Cutare ( List , info_cutat ): adresa;
Var
adr: adresa;
Begin
adr: = List;
While adr <> NIL Do
if adr.info = info_cutat
then Begin
cutare: = adr;
Exit;
End
Else
adr: = adr.succesor;
Cutare = NIL;
End.
d. Algoritmul tergere
d1. tergere_nceput : tergerea elementului de la nceputul listei;
Secvena de operaii necesar:
- salvarea adresei de eliberat;
- primul element devine succesorul fostului prim element;
- eliberarea memoriei;
LIST
a
Figura 4.6: Operaia de tergere la nceputul unei liste simplu nlnuite
Procedure tergere_nceput ( Var List )
Var liber: adresa;
Begin
liber : = List;
List : = List.succesor;
Dispose ( liber );
4.1. Lista liniar simplu nlnuit 127
End;
d2. tergere_Sfrit: tergerea ultimului element din list;
penultim
LIST
Figura 4.7: Operaia de tergere la sfritul unei liste simplu nlnuite
Secvena de operaii necesar:
- gsirea adresei penultimului element din list ;
- salvarea adresei elementului de ters ;
- succesorul penultimului element devine NIL;
- eliberarea memoriei ;
Procedure tergerea_Sfrit (List )
Var penultim, liber : adresa;
Begin
penultim : = List;
While penultim.succesor.succesor <> NIL do
penultim : = penultim.succesor;
liber : = penultim. succesor;
penultim.succesor : = NIL;
Dispose ( liber );
End;
d3. tergere_Mijloc: tergerea unui element dup un element dat din list, a
crui adres este numit dup;
Secvena de operaii necesar:
- salvarea adresei de eliberat;
- succesorul lui dup devine succesorul succesorului acestuia ( pas a.);
- eliberarea memoriei;
Procedure tergere_Mijloc ( List , dup )
Var liber : adresa;
Begin
liber : = dup.succesor;
128 4. Structuri de date
a
dup
adr_no
Figura 4.8: Operaia de tergere n interiorul unei liste simplu nlnuit
dup.succesor : = dup.succesor.succesor;
DISPOSE ( liber );
End;
e. Algoritmul modicare
Algoritmul apeleaz funcia de cutare n lista simplu nlnuit, cutnd nodul care
conine informaia nrcutat. Dac ea exist, se modic informaia existent n acel
nod cu informaia nrmodicat. Dac informaia nu exist, atunci procedura va returna
o adres vid (NIL).
Procedure MODIFICARE ( List , nrcutat , nrmodicat )
Begin
adr:= CUTARE ( List , nrcutat );
if adr = NIL then
write (

Nu exista informaia cutat !!!



)
else
begin
write (

Exista informaia cutat !!!



)
adr.info:=nrmodicat
end;
End;
4.1.3 Probleme propuse
1. S se creeze o list liniar simplu nlnuit cu trei noduri, s se iniializeze
elementele listei.
2. Denii i iniializai o list simplu nlnuit. Efectuai tergerea temporar a
unui element. Aai lista modicat, reactivai elementul.
4.1. Lista liniar simplu nlnuit 129
3. Se consider o list ce conine elemente care au ca informaie util: cod produs,
cantitate, pre. Scriei i apelai funcia care calculeaz total valoare pentru
materialele existente n list.
4. S se scrie procedurile care realizeaz diferite modaliti de tiprire a unei liste
simplu nlnuite.
5. S se scrie programul pentru adunarea a dou matrice rare, memorate sub forma
de liste liniare simplu nlnuite.
6. S se construiasc o list liniar simplu nlnuit i apoi s se scrie funciile
de inserare a unui element n list la nceput de list, la sfritul listei i n
interiorul listei.
7. Scriei funcia care efectueaz copierea unei liste, nerecursiv, cu eliminarea ele-
mentelor ce au ca informaie util o valoare mai mic dect un nivel specicat
de un parametru.
8. Modelai i programai servirea " peste rnd " la distribuirea unor produse
decitare, folosind o structur de date de tip lista liniar simplu nlnuit.
9. Numrai elementele pozitive, negative i nule ale unei liste ntr-o funcie
care dup apelare, returneaz un pointer la un vector cu trei componente, se
stocheaz rezultatele parcurgerii listei.
10. Scriei programul Pascal pentru inserarea unui element ntr-o list simplu n-
lnuit ale crei elemente sunt deja sortate cresctor, pe poziia care pstreaz
lista ordonat.
11. S se genereze o list simpl nlnuit care s conin culoarea, marca i
numrul de nmatriculare al unor autoturisme aate la o coad la benzin.
S se mute toate mainile de culoare alb n fa, iar cele roii n spate. S se
elimine din coad mainile cu numr < 1000. S se determine numrul mainilor
cu marca "DACIA".
12. Fiind dat o matrice rar, s se alctuiasc o list nlnuit n care elementele
au forma ( linia, coloana, valoarea) i valoarea diferit de 0.
S se listeze elementele aate pe diagonala principal (toate).
S se determine elementul minim de pe diagonala principal (toate).
S se elimine elementul de valoare maxim.
130 4. Structuri de date
13. S se memoreze o matrice rar sub forma unei liste nlnuite, n care elementele
matricei vor reinute n ordinea lor natural (pe linii), indiferent de ordinea
introducerii lor. S se tipreasc aceast matrice n forma normal (toate ele-
mentele, inclusiv cele nule).
4.2 Lista dublu nlnuit
4.2.1 Deniii
Observm c odat pornit cutarea ntr-o list, nu ne mai putem ntoarce napoi doar
dac o lum de la nceput. Acest lucru nu este deloc convenabil, n afar de situaia n
care nu avem de ce s ne ntoarcem napoi. Exist operaii precum: inserarea naintea
elementului curent din list sau tergerea elementului curent, care presupun referirea
la elementul dinaintea elementului curent - operaie care se realizeaz cu dicultate.
Mult mai comode sunt listele de forma prezentat n gura urmtoare, liste dublu
nlnuite, cu posibilitatea de navigare dubl [Tom, 1997].
Memorarea listelor liniare se poate face n mai multe moduri, n continuare
prezentndu-se unele dintre ele.
Alocarea secvenial (static) const n a memora elementele listei n locaii suc-
cesive de memorie, conform ordinei acestor elemente n list; n acelai timp se mem-
oreaz adresa de baz (adresa primului element al listei). Un exemplu tipic este cel
n care elementele listei sunt memorate ntr-un vector, adresa de baz ind adresa
primului element al vectorului.
Alocarea nlnuit (dinamic) presupune c ecare element al listei liniare este
nlocuit cu o celul format din trei pri: o parte conine o informaie specic al
elementului, o parte cu informaia de legtur, care conine adresa celulei corespunz-
tor urmtorului element, o parte conine adresa celului corespunztoare elementului
precedent.
O list liniar dublu nlnuit este o structur de forma:
INFO
predecesor successor
Figura 4.9: Structura unui nod al listei dublu nlnuite
Lista dublu nlnuit este un tip special de list, care necesit un spaiu mare de
memorie mai mare, n care ns n afar de informaia util, mai conine i informaia
4.2. Lista dublu nlnuit 131
de legtur a ecrui element, care cuprinde att adresa elementului precedent n list
(predecesor), ct i adresa elementului urmtor (succesor). Dac elementul succesor
sau cel predecesor nu exist, pointerii respectivi au valoarea NIL.
Elementul care are adresa succesorului NIL se va numi primul element al listei
n raport cu legtura succesor i ultim element n raport cu legtura predecesor.
Elementul care are adresa predecesorului NIL se va numi ultim element al listei n
raport cu legtura succesor i primul element n raport cu legtura predecesor.
Utilizm forma de alocare dinamic, ceea ce nseamn c n timpul rulrii pro-
gramului, n funcie de necesiti, se aloc memorie suplimentar sau se renun la
ea. Pentru alocarea dinamic utilizm tipul de date referin. Se consider secvena
de program cu implementarea elementelor, element oarecare al listei care este format
din informaia util (info) i un pointer care se refer la urmtorul element al listei:
Type
adresa = nod;
nod=Record
info : tip;
succesor : adresa;
predecesor : adresa;
End;
Var
List : adresa;
Observaie. Din pcate cei doi pointeri din ecare element al listei dublu nlnuite
consum destul de mult memorie, i de aceea listele simplu nlnuite sunt mai des
folosite.
4.2.2 Operaii specice listei
Structura i coninutul listei se poate modica prin urmtoarele operaii:
a. iniializarea unei liste ca o list vid;
b. inserarea de noi elemente n orice loc din list;
c. cutarea unor elemente n orice poziie din list;
d. tergerea de elemente din orice poziie a listei;
e. modicarea unui element dintr-o poziie dat ;
132 4. Structuri de date
Alte operaii sunt cele de caracterizare. Acestea nu modic structura listelor, ci
furnizeaz informaii despre ele. Dintre operaiile de caracterizare vom considera n
continuare:
- determinarea lungimii listei (numrul de elemente);
- localizarea elementului din list care ndeplinete o anumit condiie;
Setul de operaii, considerat n cele ce urmeaz, utilizeaz poziia curent n list,
denit ca poziia elementului accesibil la un moment dat. Operaiile de prelucrare
se refer la elementul din poziia curent. n afara acestora, sunt denite operaii
care asigur modicarea poziiei curente.
S analizm ecare operaie n parte:
a. Algoritmul creare: are loc iniializarea listei ca o list vid, adic o list fr
elemente;
Procedure Creare
List: = NIL;
End;
b. Algoritmul Inserare
b1. Inserare_nceput: inserm un element la nceputul listei ;
adr
a
c
LIST
NIL
b
NIL
Figura 4.10: Operaia de inserare la nceputul unei liste dublu nlnuite
Secvena de operaii necesar:
- alocarea de spaiu elementului nou ;
- predecesorul elementului nou devine NIL ;
- se face legtura dintre succesorul noului element i List ;
- predecesorul lui List devine noul element ;
- List preia adresa noului element ;
- introducerea informaiei ;
4.2. Lista dublu nlnuit 133
Procedure Inserare_nceput ( Var List , info_nou )
new(adr );
adr.predecesor : =NIL;
adr.succesor : = List ;
List.predecesor : = adr ;
List : = adr ;
adr.info: = info_nou ;
End;
b2. Inserare_Sfrit : inserm un element la sfritul listei ;
adr
a
b
ultim
LIST
c
Figura 4.11: Operaia de inserare la sfritul unei liste dublu nlnuite
Secvena de operaii necesar:
- gsirea adresei ultimului element ;
- alocarea spaiului elementului nou ;
- predecesorul noului element devine ultimul ;
- succesorul ultimului element devine noul element ;
- introducerea de informaii ;
- modicarea adresei ultimului element ;
Procedure Inserare_Sfrit ( Var List , info_nou )
Var
ultim : adresa ;
Begin
ultim : = List;
while ultim.succesor <> NIL do
ultim : = ultim.succesor
new (adr);
adr.predecesor : = ultim;
134 4. Structuri de date
ultim. succesor : = adr;
adr.succesor : = NIL;
adr.info: = info_nou;
ultim : = adr;
End;
b3. Inserare_Mijloc: inserm un element nou dup un element dat din list, a
crui adres este numit dup;
adr
dup
a
Figura 4.12: Operaia de inserare n interiorul unei liste dublu nlnuite
Secvena de operaii necesar:
- alocare de spaiu ;
- predecesorul noului element devine elementul listei ;
- predecesorul succesorului lui dup devine noul element ;
- succesorul elementului nou devine succesorul elementului dup;
- introducem informaia nou ;
Procedure Inserare_Mijloc ( Var List , dup , info_nou )
new (adr) ;
adr.predecesor : = dup ;
dup.succesor.predecesor : = adr ;
adr.succesor : = dup.succesor : = adr ;
adr.info : = info_nou ;
End;
c. Algoritmul Cutare:
Algoritmul caut n lista dublu nlnuit nodul care conine informaia info_cutat.
Dac ea exist, funcia de cutare va returna adresa nodului ce conine informaia
cutat. Dac informaia nu exist, atunci funcia va returna o adres vid (NIL).
Cutarea se poate face bidirecional, pe legtura succesor sau pe legtura predecesor.
4.2. Lista dublu nlnuit 135
Function Cutare ( List , info_cutat ): adresa;
Var
adr : adresa ;
Begin
adr:=List;
while adr < > NIL do
if adr.info = info_cutat then
begin
Cutare: = adr ;
exit;
end
else
adr: = adr.succesor ;
Cutare: = NIL ;
End;
d. Algoritmul tergere
d.1 tergere_nceput : tergerea elementului de la nceputul listei ;
LIST
a
Figura 4.13: Operaia de tergere la nceputul unei liste dublu nlnuite
Secvena de operaii necesar:
- salvarea adresei de eliberat ;
- predecesorul succesorului lui List s devin NIL ;
- List devine succesorul primului element ;
- predecesorul lui List devine NIL ;
- eliberarea memoriei ;
Procedure tergere_nceput ( Var List )
Var
liber : adresa ;
Begin
if List = NIL then
136 4. Structuri de date
write(" Lista este vid ")
else
Begin
liber: = List ;
List: = List.succesor ;
List.predecesor: = NIL ;
Dispose ( liber ) ;
End;
End;
d.2 tergere_Sfrit : tergerea ultimului element din list ;
liber
LIST
Figura 4.14: Operaia de tergere la sfritul unei liste dublu nlnuite
Secvena de operaii necesar:
- gsirea adresei ultimului element din list ;
- salvarea adresei elementului de ters ;
- succesorul predecesorului lui ultim devine NIL;
- eliberarea memoriei ;
Procedure tergerea_Sfrit ( Var List )
Var
ultim , liber : adresa ;
Begin
ultim : = List ;
whileultim.succesor < > NIL do
ultim : = ultim.succesor ;
liber : = ultim ;
ultim.predecesor.succesor : = NIL ;
Dispose( liber ) ;
End;
d.3 tergere_Mijloc : tergerea unui element dup un element dat din list, a
crui adres este numit dup;
Secvena de operaii necesar:
- salvarea adresei de eliberat ;
4.2. Lista dublu nlnuit 137
liber dup
Figura 4.15: Operaia de tergere la sfritul unei liste dublu nlnuite
- predecesorul succesorului dup devine predecesorul lui dup ;
- succesorul predecesorului dup devine succesorul lui dup ;
- eliberarea memoriei ;
Procedure tergere_Mijloc ( Var List, dup )
Var
liber : adresa ;
Begin
liber : = dup.succesor ;
liber.succesor.predecesor = dup ;
dup.succesor : = liber.succesor ;
Dispose ( liber );
End;
e. Modicare (Actualizare) :
Algoritmul apeleaz funcia de cutare n lista dublu nlnuit, cutnd nodul care
conine informaia nrcutat. Dac ea exist, se modic informaia existent n acel
nod cu informaia nrmodicat. Dac informaia nu exist, atunci procedura va returna
o adres vid (NIL). Cutarea informaiei de modicat se poate face pe ambele
legturi, predecesor i succesor.
Procedure MODIFICARE ( List , nrcutat , nrmodicat )
Begin
adr := CUTARE ( List , nrcutat );
if adr = NIL then
write ( Nu exista informaia cutat !!! ) ;
else
begin
write ( Exista informaia cutat !!! ) ;
adr.info := nrmodicat ;
end;
138 4. Structuri de date
End;
4.2.3 Probleme propuse
1. S se construiasc o list dublu nlnuit i s se scrie elementele acesteia n
ambele sensuri, n funcie de opiune. S se tearg apoi un element al listei i
s tipreasc lista rezultat.
2. S se construiasc o list dublu nlnuit cu 5 elemente citite dintr-un vector.
S se scrie funcia recursiv de tiprire a listei n ambele sensuri. S se scrie
funcia de tergere a unui element din list.
3. Scriei i apelai funcia care veric dac matricea rar ptratic ale crei ele-
mente sunt stocate ntr-o list conine numai elemente ale diagonalei principale.
4. S se construiasc un arbore genealogic (folosind o list nlnuit) utiliznd
pentru ecare membru introdus legturile de tip : printe, copil (primul), frate,
so_soie. S se gseasc, pentru membrul dat, toi verii de grad I (copiii frailor
prinilor).
5. S se creeze o list nlnuit cu articole cu structura : Nume_student, An,
Grup, Medie. S se listeze toi studenii cu media > 9 iar apoi s se elimine
din list toi studenii din anul 5.
6. Fiind dat o matrice ale crei elementele reprezint localiti, s se construiasc
o list, n care pentru ecare localitate se vor memora legturile cu localitile
nvecinate n cele patru direcii (N, E, S, V). S se parcurg un traseu, plecnd
de la o anumit localitate de start, urmnd un ir de direcii ( Se vor ignora
direciile inaccesibile).
7. O matrice rar poate memorat printr-o list dublu nlnuit avnd ca el-
emente elementele nenule ale matricei respective. Fiecare linie sau coloan va
reprezentat printr-o list dublu nlnuit. Se cere un program care s per-
mit memorarea unei astfel de matrice rare i efectuarea de operaii de citire,
adunare, scdere sau nmulire i de asemenea tiprirea unei matrice.
8. S se construiasc o list nlnuit cu componentele de forma: X
i
, Leg_Urm,
Leg_Prim, unde X
i
N i X
i
< X
j
pentru i < j, Leg_Urm este adresa
urmtorului element din list, iar Leg_Prim este adresa ultimului numr prim
dinaintea lui X
i
. S se listeze toate numerele X
i
n ordine cresctoare, apoi doar
numerele prime din list n ordine descresctoare.
4.3. Stiva (stack) 139
9. Se d o list nlnuit. Se cere o procedur care s permit adugarea unui
element pe poziia n; (dac lista conine mai puine de n 1 elemente, adu-
garea se va efectua n coada listei) i o procedur care s efectueze tergerea
elementului de pe poziia n (dac lista conine mai puin de n elemente, se va
terge ultimul element).
10. Se citete un ir X
1
, X
2
, . . . , X
N
de numere naturale distincte i un numr nat-
ural b > 1, n funcie de care irul dat se poate mpri n b subiruri astfel:
X
i
S
k
dac restul mpririi lui X
i
la b este k. S se construiasc o list de
forma: X
i
, Leg_Sir, Leg_Elem, unde Leg_Sir este adresa primului element
din urmtorul subir, iar Leg_Elem este adresa urmtorului element din acelai
subir. Pentru un numr k dat, s se listeze subirul S
k
.
11. S se depun numerele reale X
1
, X
2
, . . . , X
N
ntr-o list, apoi s se ordoneze
cresctor aceast list folosind o procedur care aduce elementul minim pe prima
poziie i o procedur care mut elementul pe ultima poziie.
12. Se d o mulime de maini caracterizate prin culoare, marc, numr. S se
construiasc o list cu toate mainile avnd acea culoare. S se listeze numerele
de nmatriculare ale mainilor care au o culoare i o marc dat.
13. Fiind dat o list cu numerele naturale X
1
, X
2
, . . . , X
n
, s se elimine elementele
care se repet, apoi dup ecare element s se adauge divizorii si.
14. Se dau numerele reale a, X
1
, X
2
, . . . , X
n
. S se construiasc o list care s
poat parcurs n ambele sensuri, apoi s se elimine din list primul i ultimul
element egal cu a.
4.3 Stiva (stack)
4.3.1 Generaliti
O stiv (n englez stack), este o list liniar de un tip special, n care adugarea
sau scoaterea unui element se face la un singur capt al listei, numit vrful stivei.
Primul element introdus n stiv poart numele de baz a stivei. O stiv fr nici un
element se numete stiv vid sau stiv goal. Ca orice list liniar, o stiv poate
realizat practic (implementat) e folosind o reprezentare static (secvenial), e
prin reprezentare dinamic (nlnuit). Indiferent de reprezentare, implementarea
presupune alocarea unui spaiu limitat, dac el este n ntregime ocupat, spunem c
stiva este plin.
140 4. Structuri de date
Stiva se poate asemna unui vraf de farfurii aezat pe o mas, modalitatea cea mai
comod de a pune o farfurie ind n vrful stivei, tot de aici ind cel mai simplu s se
ia o farfurie. Datorit locului unde se acioneaz asupra stivei, operaiile de inserare
i extragere, aceste structuri se mai numesc liste de tip LIFO (Last In - First Out),
adic ultimul sosit - primul ieit [Tud, 1993].
4.3.2 Stiva alocare static
n reprezentarea secvenial, elementele stivei vor memorate ntr-un vector (tabel)
numit Stiva cu n componente, n ind capacitatea maxim a stivei. Vom nota cu
TOP numrul efectiv de elemente din stiv, i anume:
TOP = 0 va reprezenta o stiv goal (deci nu vom mai putea extrage elemente
din stiv)
TOP >= n - va reprezenta o stiv plin (deci nu vom mai putea insera elemente
n stiv)
D C B A LIFO
TOP
Figura 4.16: Reprezentare unei stive secveniale
Operaiile efectuate asupra stiva sunt:
a. testare capacitate superioar (stiv plin);
b. testare capacitate inferioar (stiv goal);
c. inserare de noi elemente, operaie numit PUSH
d. extragere (tergere) din stiv, operaie numit POP.
a. Testare capacitate superioar (stiv plin);
Function Full_Stack(TOP:integer): boolean
Begin
If TOP = n then
Full_Stack:=TRUE
else
Full_Stack:=FALSE;
End;
4.3. Stiva (stack) 141
b. Testare capacitate inferioar (stiv goal);
Function Empty_Stack(TOP:integer): boolean
Begin
If TOP = 0 then
Empty_Stack:=true
else
Empty_Stack:=false;
End;
c. Inserare - Push;
Procedure PUSH ( var TOP:integer, info_nou:tip)
Begin
If NOT FULL_Stack(TOP) then
Begin
Stiva[TOP]:=info_nou;
TOP=TOP+1;
else
writeln(OVERFLOW);
End;
d. Extragere - Pop;
Function Pop (VAR TOP:integer):tip
Begin
If NOT Empty_Stack(TOP) then
Begin
TOP=TOP-1;
Pop:=Stiva[TOP];
else
writeln(UNDERFLOW);
End;
4.3.3 Stiva alocare dinamic
n reprezentarea dinamic, stiva va implementat cu ajutorul unei liste simplu
nlnuite. Adresa ultimului element din stiv va numit TOP, avnd semnicaia
de a indica spre elementul din vrful stivei. Structura va manipulat ca i orice list
142 4. Structuri de date
simplu nlnuit, prin adresa primului element, notat LIST, care va semnica baza
stivei.
TOP
LIST
NIL
Figura 4.17: Reprezentare unei stive dinamice
Operaiile efectuate asupra stiva sunt:
1. testare capacitate inferioar (stiv goal);
2. inserare de noi elemente, operaie numit Push
3. extragere (tergere) din stiv, operaie numit Pop.
Observaie. Memoria ind alocat dinamic nu este necesar testul de capacitate su-
perioar.
a. Testare capacitate inferioar (stiv goal);
Function Empty_Stack(Top:adresa): boolean
Begin
If Top = Nil then
Empty_Stack:=True
else
Empty_Stack:=False;
End;
b. Inserare - Push;
Procedure Push ( var Top:adresa, info_nou:tip)
Begin
Inserare_sfrsit(List,Top,info_nou)
End;
4.3. Stiva (stack) 143
c. Extragere - Pop;
Function Pop (var Top:adresa):tip
Begin
If NOT Empty_Stack(Top) then
tergere_sfrsit(List,Top)
else
writeln(Underow);
End;
4.3.4 Probleme propuse
1. S se realizeze evidena materialelor existententr-o magazie. La intrarea n
stoc a materialelor pe baza de factur, se adaug elementele ntr-o stiv. La
eliberarea spre consum productiv, se terge vrful stivei. Procedeul continu,
dup cum avem intrri sau consumuri de materiale. Se va scrie i funcia pentru
numrarea facturilor.
2. Se consider o stiv nevid de lungime mai mare ca 5. Scriei funcia pentru
dealocarea memoriei ocupate de aceast stiv .
3. O echip realizeaz demontarea unei instalaii cu dispunerea reperelor i sub-
ansamblelor ntr-un mod corespunztor reparrii i mai apoi asamblri. O alt
echip efectueaz asamblarea. Scriei programul care aeaz lista operaiilor
de asamblare tiind ca aceste operaii sunt specicate prin numele reperelor sau
sub-ansamblelor.
4. Se consider mulimea literelor mari i mulimea literelor mici. S se constru-
iasc, pornind de la un ir oarecare de litere, dou stive ce conin literele mari,
respectiv, literele mici.
S se aeze literele mici i mari n ordinea n care au fost introduse.
5. Scriei i apelai funcia de tergere a unei stive pn la elementul a crui infor-
maie util coincide cu un parametru dat.
6. Dndu-se stivele A i B care conin cod produs, cantitate i, respectiv, cod
produs i pre, creai stiva ale crei elemente conine cod produs, cantitate i
pre. La apelarea funciei, elementele sunt presupuse sortate dup cod.
7. Descompunei, folosind o funcie pe care o apelai, o stiv n dou stive cu
numr egal de elemente, numai dac acest lucru este posibil.
144 4. Structuri de date
8. Gsii o formul simpl pentru numrul de permutri de n elemente, ce pot
obinute cu ajutorul unei stive.
9. Artai c permutarea p
1
, p
2
, . . . , p
n
se poate obine pornind de la 1, 2, . . . , n
utiliznd o stiv dac i numai dac nu exist indici i < j < k astfel nct
p
j
< p
k
< p
i
.
4.4 Coada (queue)
4.4.1 Generaliti
n prelucrarea unei mulimi de elemente pot s e utilizate diferite metode de alegere
a urmtorului element supus prelucrrii [Dal, 1988]. Aceast alegere poate s e
aleatoare sau s respecte un anumit criteriu. De exemplu, pentru o mulime la care
este semnicativ ordinea n care elementele au fost introduse n mulime se poate
considera un criteriu care s se bazeze pe aceast ordine. Modelul intuitiv al acestei
structuri este coada care se formeaz la un magazin, lumea se aeaz la coad la
sfritul ei, cei care se gsesc la nceputul cozii sunt servii, i prsesc apoi coada.
Coada reprezint o alt categorie special de list liniar, n care toate elementele
se insereaz la un capt (sfrit) i se extrag (terg) la cellalt capt (nceput).
Prelund o terminologie din domeniul sistemelor de operare, coada mai poart
numele de list FIFO (First In - First Out), adic primul intrat n coad va
primul care va iei din coad.
4.4.2 Coada alocare static
n reprezentarea secvenial, elementele cozii vor memorate ntr-un vector (tabel)
numit coada cu n componente, n ind capacitatea maxim a stivei. Vom nota cu
Front indexul elementului ce urmeaz a servit, iar cu Rear indexul primului element
liber din coad. Dac:
Front = Rear va reprezenta o coad goal (deci nu vom mai putea extrage
elemente din coad)
Rear >= n - va reprezenta o coad plin (deci nu vom mai putea insera elemente
n coad)
Operaiile efectuate asupra cozii sunt:
a. testare capacitate superioar (stiv plin);
b. testare capacitate inferioar (stiv goal);
4.4. Coada (queue) 145
inserare
extragere
Front Rear
Figura 4.18: Reprezentare unei cozi secveniale
c. inserare de noi elemente, operaie numit Enqueue;
d. extragere (tergere) din stiv, operaie numit Dequeue.
a. Testare capacitate superioar (coad plin);
Function Full_Queue(Rear:integer): boolean
Begin
If Rear = n then
Full_Queue:=True
else
Full_ Queue:=False;
End;
b. Testare capacitate inferioar (coad goal);
Function Empty_ Queue (Front, Rear:integer): boolean
Begin
If Front = Rear then
Empty_ Queue:=True
else
Empty_ Queue:=False;
End;
c. Inserare - Enqueue;
Procedure Enqueue ( var Rear:integer, info_nou:tip)
Begin
If not Full_Queue(Rear) then
Begin
Coada[Rear]:=info_nou;
146 4. Structuri de date
Rear=Rear+1;
else
writeln(Overow);
End;
d. Extragere - Dequeue;
Function Dequeue( var Front:integer):tip
Begin
If NOT Empty_Queue(Front, Rear) then
Begin
Dequeue:=coada[Front];
Front : =Front+1;
else
writeln(Underow);
End;
4.4.3 Coada alocare dinamic
n reprezentarea dinamic, coada va implementat cu ajutorul unei liste simplu
nlnuite. Adresa ultimului element din stiv va numit Rear, avnd semnicaia
de a indica adresa ultimul element inserat n coad. Adresa primului element din stiv
va numit Front, avnd semnicaia de a indica adresa primului element inserat n
coad, deci a elementului care urmeaz a extras.
Front Rear
NIL
Figura 4.19: Reprezentare unei stive dinamice
a. testare capacitate inferioar (coad goal);
b. inserare de noi elemente n coad, operaie numit Enqueue;
c. extragere (tergere) din coad, operaie numit Dequeue.
4.4. Coada (queue) 147
Observaie. Memoria ind alocat dinamic nu este necesar testul de capacitate su-
perioar.
a. Testare capacitate inferioar (coad goal);
Function Empty_Queue(Front:adresa): boolean
Begin
If Front = NIL then
Empty_Stack:=True
else
Empty_Stack:=False;
End;
b. Inserare - Enqueue;
Procedure Enqueue ( var Rear:adresa, info_nou:tip)
Begin
Inserare_sfrsit(Front,Rear,info_nou);
End;
c. Extragere - Dequeue;
Function DEQUEUE( varFront:adresa):tip
Begin
If not Empty_Queue(Front) then
tergere_sfrsit(List,Top)
else
writeln(Underow);
End;
4.4.4 Probleme propuse
1. O coad biterminal cu restricii la intrare este o list liniar n care elementele
nu pot inserate dect la un capt, dar pot terse de la ambele capete; n
mod clar o astfel de coad biterminal poate opera att ca o stiv ct i ca o
coad, dac nu tergem elemente dect da la un singur capt. Se poate ca i o
coad biterminal cu restricii la ieire s opereze ca o coad?
2. Exist permutri ale elementelor 1, 2, . . . , n care nu pot obinute cu ajutorul
unei cozi care nu este cu restricii nici la intrare, nici la ieire ?
148 4. Structuri de date
3. Folosind o structur de tip stiv i coad s se decid dac un cuvnt este
palindrom. Un palindrom este un cuvnt care coincide cu inversul su. Exemple:
lupul este palindrom, acesta nu este palindrom.
4. Se introduc n numere reale ntr-o stiv i ntr-o coad. Se extrage un numr din
stiv i se introduce n coad. Se extrage un numr din coad i se introduce n
stiv. S se tipreasc coninutul stivei i al cozii dup k pai.
4.5 Arborele binar
Cnd am discutat despre structurile de date nlnuite, liste simplu sau dublu n-
lnuite, am vzut avantajele evidente ale stocrii de date ordonate. Folosirea ecient
a spaiului de memorare, manipularea ntregii structuri de date doar prin intermediul
adresei de nceput, etc. sunt doar cteva din argumentele folosirii acestor structuri de
date dinamice. Dezavantajul evident al structurilor de date de tip list nlnuit este
ns provocat de procedurile de cutare secvenial care au o performan de ordinul
O(n). De aceea, s-a construit o nou structur de date dinamic, de tip nlnuit,
care s pstreze avantajele exibilitii structurii de date tip list nlnuit i s
se bazeze pe o performan mult mbuntit a algoritmului de cutare, de ordinul
O(log
2
n).
4.5.1 Deniii
Un arbore este o mulime de elemente numite noduri , un singur nod avnd rolul de
nod rdcin, mpreun cu o relaie de tip printe-u care denete o structur
ierarhic pe mulimea nodurilor. n mod formal, un arbore poate denit recursiv
astfel [Aho, 1987]:
1. Un arbore poate conine un singur nod. Acest nod este i nodul rdcin al
arborelui.
2. Fie n un nod i T
1
, T
2
, . . . , T
k
arbori cu nodurile rdcin n
1
, n
2
, . . . , n
k
. Putem
construi un nou arbore, fcnd ca nodul n s devin nodul printe al nodurilor
n
1
, n
2
, . . . , n
k
. n acest arbore, n este nodul rdcin, iar T
1
, T
2
, . . . , T
k
se
numesc subarbori. Nodurile n
1
, n
2
, . . . , n
k
se numesc noduri u ale nodului
n.
Un arbore binar este o structur arborescent n care ecare vrf are cel mult doi
descendeni, fcndu-se ns distincie clar ntre descendentul drept i descendentul
4.5. Arborele binar 149
stng al ecrui vrf. Se accept i arborele binar cu 0 vrfuri, numit arbore binar
vid.
Arborii binari nu reprezint cazuri particulare de arbori orientai, dect dac
se face abstracie de distincia menionat ntre descendentul drept i cel stng al
ecrui vrf. ntr-adevr dac un vrf are un singur descendent, aceast informaie
este sucient n cazul unui arbore, dar insucient n cazul unui arbore binar, cnd
trebuie precizat dac acest descendent este descendent stng sau descendent drept.
ntr-o structur de tip arbore, elementele sunt structurate pe nivele; pe primul
nivel, numit nivel 0, exist un singur nod numit rdcin, de care sunt legate mai
multe noduri, numite i care formeaz nivelul 1; de acestea sunt legate elementele
de pe nivelul 2 .a.m.d.
nivel 0
g
f
c b
a
d e
nivel 1
nivel 2
nivel 3
Figura 4.20: Exemplu de arbore i organizarea sa pe nivele
Un arbore este compus din elementele numite noduri sau vrfuri i legturile
dintre acestea. Un nod situat pe un anumit nivel este nod tat pentru nodurile
legate de el, situate pe nivelul urmtor, acestea reprezentnd ii si. Fiecare nod
are un singur tat, cu excepia rdcinii care nu are tat. Nodurile fr i se numesc
noduri terminale sau noduri frunz.
Termenii nod tat, nod u, nod bunic, nod nepot sau nod frate sunt preluai
de la arborii genealogici, cu care arborii se aseamn foarte mult.
Arborii, ca structuri dinamice de date, au extrem de multe aplicaii n informatic.
Deosebit de utilizat n aplicaii este structura de tip arbore binar AB. Un arbore
binar este un arbore n care ecare nod are cel mult doi i, ul stng i ul
drept (ul stng este legat n stnga tatlui i cel drept n dreapta). Dac se elimin
rdcina i legturile ei, se obin doi arbori binari care se numesc subarborele stng
i subarborele drept ai arborelui iniial.
150 4. Structuri de date
Arborele binar este, deci, o structur recursiv de date. Un arbore binar nevid
e se reduce la rdcin, e cuprinde rdcina i cel mult doi subarbori binari. Un
arbore binar se poate implementa foarte uor cu ajutorul adreselor de nlnuire,
ecare element cuprinznd, n afar de informaia proriu-zis asociat nodului, adresa
ului stng i adresa ului drept, acestea exprimnd legturile existente ntre noduri.
Implementarea arborilor binari
n majoritatea implementrilor i cei doi subarbori sunt adresai indirect; n funcie
de varianta de implementare - dinamic sau static, adresarea se realizeaz e prin
intermediul pointerilor, e prin intermediul indicilor de tablou.
Alegem implementarea dinamic cea mai simpl form de reprezentare a nodurilor.
Un nod al unui arbore binar AB are urmtoarea structur:
Info Fiu_dr Fiu_st
Figura 4.21: Structura nodului unui arbore binar
unde:
Fiu_st : reprezint adresa ului stnga;
Info: informaia atat nodului.;
Fiu_dr: reprezint adresa ului dreapta;
Structura nodului n implementarea Pascal este urmtoarea [Alb, 1994]:
Type
Adresa = Nod
Nod = Record
Fiu_st : Adresa;
Info : tipinfo;
Fiu_dr : Adresa;
end
4.5.2 Operaii ntr-un arbore binar AB
Operaiile n cazul arborilor binari sunt:
a. creare-iniializare;
b. inserare;
4.5. Arborele binar 151
c. cutare;
d. tergere;
e. traversarea:
Ne vom ocupa doar de operaia de traversare care nu este dependent de orga-
nizarea particular a arborelui, ind aceeai pentru toi arborii binari. Construirea
unui arbore binar se face n funcie de relaia denit pe datele coninute n nodurile
arborelui binar. n general, se alege o parte a datei stocat n nodurile arborelui
binar, dup care se va ordona noua structur de date arborescent. Informaia dup
care se ordoneaz arborele binar se numete cheie [Hor, 1978].
Cea mai des utilizat form de organizare a unui arbore binar este urmtoarea:
Cheia nodului u stnga < Cheia nodului tat <
Cheia nodului u stnga
(4.1)
Utiliznd formula de mai sus se obin arbori binari speciali, utilizai pentru orga-
nizarea i cutarea datelor, numii arbori binari de cutare ABC.
e. Traversarea arborelui binar.
Operaia de traversare const n parcurgerea pe rnd a nodurilor n vederea prelucrrii
informaiilor ataate acestora. Traversarea arborelui presupune vizitarea ecrui nod
o singur dat, operaie echivalent cu o liniarizare a arborelui. Exist trei modaliti
importante de traversare a unui arbore binar, exprimate prin regulile recursive:
1. n preordine: se viziteaz rdcina, apoi tot n preordine se viziteaz nodurile
subarborelui stng i apoi nodurile subarborelui drept.
2. n inordine: se viziteaz n inordine nodurile subarborelui stng, apoi rdcina
i apoi tot n inordine, nodurile subarborelui drept.
3. n postordine: se viziteaz n postordine nodurile subarborelui stng, apoi tot
n postordine, nodurile subarborelui drept i, la sfrit, rdcina.
Observaie.
1. evident, dac arborele se reduce la un singur nod, vizitarea acestuia n preor-
dine, inordine sau postordine presupune parcurgerea acestuia, deci prelucrarea
informaiilor asociate lui;
2. cele trei modaliti de traversare difer prin, momentul n care se viziteaz
rdcina i anume, n cazul:
152 4. Structuri de date
- preordine: se viziteaz nti rdcina, apoi subarborele stng i dup
aceea cel drept (RSD Rdcin, Stnga, Dreapta);
- inordine: se viziteaz subarborele stng, se viziteaz rdcina i subar-
borele drept (SRD - Stnga, Rdcin, Dreapta);
- postordine: se viziteaz subarborele stng, se viziteaz subarborele drept
i rdcina (SDR - Stnga, Dreapta, Rdcin);
Descrierea algoritmilor de traversare, n limbajul Pascal este:
Procedure inordine ( def : adresa ) ; { traversare inordine }
begin
if def <> nil then
begin
inordine (def .u_st ) ;
write ( def.info : 3 ) ;
inordine ( def.u_dr ) ;
end ;
end ;
Procedure preordine ( def : adresa ) ; { traversare preordine }
begin
if def <> nil then
begin
write ( def.info : 3 ) ;
preordine ( def.u_st ) ;
preordine ( def.u_dr ) ;
end ;
end ;
Procedure postordine ( def : adresa ) ; { traversare postordine }
begin
if def <> nil then
begin
postordine ( def.u_st) ;
postordine( def.u_dr );
write ( def.info : 3 ) ;
end ;
end ;
4.6. Grafuri 153
4.5.3 Probleme propuse
1. Cte structuri arborescente diferite exist pentru trei noduri A, B i C ?
2. Exist arbore binar care s nu e arbore ?
3. S se creeze arborele genealogic propriu pe parcursul a trei sau patru generaii,
punndu-se n nodul rdcin prenumele iar n nodurile descendente ale ecrui
nod, numele prinilor.
4. Pentru arborele binar din gura 4.20 s se scrie listele de vrfuri obinute n
urma celor trei metode de parcurgere.
5. S se scrie un program pentru determinarea adncimii maxime a unui arbore
binar, adic al numrului de nivel maxim asociat nodurilor terminale.
6. S se scrie un program pentru listarea tuturor nodurilor aate pe un nivel dat
ntr-un arbore binar.
7. Aplicnd cele trei metode de parcurgere a unui arbore binar, s se extrag, n
ordinea n care apar, nodurile descendente, n ordinea de la stnga la dreapta.
8. S se conceap algoritmi de prelucrare (creare, parcurgere etc.) pentru ar-
borescene, utiliznd pentru ecare nod cte o list cu toate nodurile descen-
dente, n ordinea de la stnga la dreapta.
9. S se scrie un algoritm care, pe baza succesiunii nodurilor n inordine i pos-
tordine ale unui arbore binar, s produc succesiunea n preordine a acestora.
Analog, pe baza succesiunilor n ordine i preordine, s se obin lista nodurilor
n postordine.
4.6 Grafuri
4.6.1 Grafuri orientate
4.6.1.1 Deniii i generaliti
Deniia 4.6.1. Un graf orientat este un cuplu G = (X, U), unde X este o mulime
nit i nevid de elemente numite vrfuri, i U XX este o mulime de elemente
numite arce.
Fie un arc u = (x, y) U. Spunem c arcul u este incident exterior cu vrful
x, este incident interior cu vrful y, i are sensul (orientarea) de la x la y. Vrful
154 4. Structuri de date
x este extremitate iniial i predecesorul lui y, i vrful y este extremitate nal i
succesorul lui x. Deci n precizarea unui arc conteaz ordinea vrfurilor.
Dou vrfuri sunt adiacente dac ntre ele exist un arc. Dou arce distincte sunt
adiacente dac au o extremitate comun.
Deniia 4.6.2. Un graf orientat este un cuplu G = (X, ), unde X este o mulime
de elemente numite vrfuri, i este o aplicaie multivoc : X X (adic o funcie
denit pe X cu valori n familia P(X) a prilor lui X).
Dac x X atunci y (x) precizeaz c de la vrful x la vrful y exist un arc
i spunem c y este succesor al lui x. Spunem c x este predecesor al lui y i notm
x
1
(y).
Se d un graf G = (X, ) i e x X un vrf. Notm cu g
+
(x) numrul succeso-
rilor si, adic [(x)[; acest numr se numete semigradul exterior al lui x. Notm cu
g

(x) numrul predecesorilor si, adic [


1
(x)[; acest numr se numete semigradul
interior al lui x. Suma g(x) = g
+
(x) +g

(x) se numete gradul lui x. Dac g(x) = 0


spunem c vrful x este izolat.
Cele dou deniii sunt analoge:
(x) = y X [ (x, y) U; (x, y) U y (x).
Deniia 4.6.3. Un graf orientat este simetric dac pentru orice pereche de vrfuri
x, y X avem: (x, y) U (y, x) U.
Un graf este bipartit dac exist o partiie X = X
1

X
2
astfel nct pentru orice
(x, y) U avem x X
1
i y X
2
.
Un graf G

= (A, V ) este subgraf al grafului G = (X, U) dac A X i V =


(AA)

U.
Un graf G

= (X, V ) este graf parial al grafului G = (X, U) dac V U.


Un graf G

= (A, V ) este subgraf parial al grafului G = (X, U) dac A X i


V (AA)

U.
Deniia 4.6.4. Fiind dat un graf orientat G = (X, U), un drum n graful G este
o succesiune de arce cu proprietatea c extremitatea terminal a unui arc coincide
cu extremitatea iniial a arcului urmtor din drum. Un drum se poate deni i
prin succesiunea de vrfuri care sunt extremiti ale arcelor ce compun drumul: o
succesiune de vrfuri cu proprietatea c orice dou vrfuri consecutive sunt unite
printr-un arc [Tom, 1981].
Un drum ntr-un graf este:
simplu, dac nu folosete de dou ori un acelai arc;
compus, dac nu e simplu;
4.6. Grafuri 155
elementar, dac nu trece de dou ori prin acelai vrf;
eulerian, dac este simplu i folosete toate arcele grafului;
hamiltonian, dac este elementar i trece prin toate vrfurile grafului;
circuit, dac extremitatea iniial a drumului coincide cu cea nal.
4.6.1.2 Reprezentarea grafurilor orientate
a. Reprezentarea cu ajutorul matricelor de adiacen
Fie un graf orientat G = (X, U), unde presupunem c G = 1, 2, . . . , n. Matricea de
adiacen A asociat grafului este o matrice ptratic de ordinul n, denit astfel:
A[i, j] =
_
_
_
1, dac (i, j) U
0, dac (i, j) / U
(4.2)
Exemplul 4.6.1. S considerm graful reprezentat n gura de mai jos:
1
4 3
2
Figura 4.22: Exemplu de graf orientat
Atunci matricea de adiacen ataat grafului este:
A =
_
_
_
_
_
0 1 1 0
0 0 0 1
0 1 0 0
0 0 1 0
_
_
_
_
_
Dezavantajul utilizrii reprezentrii grafurilor orientate cu ajutorul matricelor de adi-
acen este dat de faptul c spaiul ocupat este de ordinul (n
2
). Orice operaie
efectuat asupra grafului orientat necesit parcurgerea matricei de adiacen asociat,
care este o operaie de ordinul O(n
2
).
156 4. Structuri de date
b. Reprezentarea cu ajutorul listelor de adiacen
Pentru a elimina dezavantajele reprezentrii grafurilor orientate cu ajutorul ma-
tricelor de adiacen putem folosi o metod bazat pe reprezentarea cu liste nlnuite,
numit reprezentare cu liste de adiacen.
Lista de adiacen pentru un vrf i este o list simplu nlnuit a tuturor nodurilor
adiacente cu i. n acest fel reprezentarea grafului orientat G = (X, U), se face cu o
tabel n dimensional numit CAP, elementul CAP[i] reprezentnd un pointer ctre
capul listei de adiacen al vrfului i.
Exemplul 4.6.2. Reprezentarea grafului din Figura 4.22 cu ajutorul listelor de adi-
acen:
CAP
1
4
3
2
3
2
4
3
2
Figura 4.23: Reprezentarea grafului orientat din Figura 4.22 cu ajutorul listelor de
adiacen
Reprezentrii grafurilor orientate cu ajutorul listelor de adiacen necesit un
spaiu de memorare ocupat este de ordinul (n+nr.de_arce). De aceea, aceast
form de reprezentare este preferabil atunci cnd expresia n+nr.de_arce este mai
mic dect n
2
. De asemenea constatarea faptului dac exist sau nu un arc de la
vrful i la vrful j necesit un timp proporional cu O(n).
4.6. Grafuri 157
4.6.2 Grafuri neorientate
4.6.2.1 Deniii i generaliti
Deniia 4.6.5. Un graf neorientat este un cuplu G = (X, U), unde X este o mulime
de elemente numite vrfuri, i U este o mulime de perechi neordonate de vrfuri
numite muchii. O muchie (x, y) nu are orientare, astfel c (x, y) = (y, x).
O muchie este incident vrfurilor care sunt extremiti ale sale. Dou vrfuri
sunt adiacente dac ntre ele exist o muchie. Dou muchii sunt adiacente dac au o
extremitate comun. Gradul unui vrf x este numrul de muchii incidente cu acesta
i se noteaz g(x).
Deniia 4.6.6. Un lan este o succesiune de muchii cu proprietatea c orice muchie
are un vrf comun cu muchia precedent i cellalt vrf comun cu muchia succesoare.
n mod analog denim noiunea de ciclu corespunztoare noiunii de circuit de la
grafuri orientate.
Deniia 4.6.7. Un graf neorientat este conex dac ntre orice dou vrfuri exist
un lan.
O component conex a unui graf neorientat este un subgraf conex maximal n
raport cu operaia de incluziune. Cu alte cuvinte, nu exist o submulime de vrfuri
mai numeroas care s induc un subgraf conex.
Deniia 4.6.8. Un arbore este un graf conex fr cicluri.
Lema 4.6.1. Un arbore cu n vrfuri are n 1 muchii.
Demonstraie [Liv, 1986]. Considerm pentru nceput un graf cu dou vrfuri unite
printr-o muchie, care este evident un arbore. La ecare pas adugm un vrf nou pe
care l unim printr-o muchie cu un vrf deja existent. Presupunem c dup un numr
de pai avem un arbore cu k vrfuri i k 1 muchii. La urmtorul pas obinem un
arbore parial cu k +1 vrfuri i k muchii. Nu se obine nici un ciclu: pentru aceasta
ar trebuit ca noul vrf ales s fost deja conectat cu unul din cele k vrfuri, fapt
imposibil.
158 4. Structuri de date
4.6.2.2 Reprezentarea grafurilor neorientate
a. Reprezentarea cu ajutorul matricelor de adiacen
Fie un graf neorientat G = (X, U), unde presupunem c G = 1, 2, . . . , n. Matricea
de adiacen A asociat grafului este o matrice ptratic de ordinul n, denit astfel:
A[i, j] =
_
_
_
1, dac (i, j) U
0, dac (i, j) / U
(4.3)
Observaie. Se observ c matricea de adiacen ataat grafului este simetric n
raport cu diagonala principal.
Exemplul 4.6.3. S considerm graful reprezentat n gura de mai jos:
1 2
4
3
Figura 4.24: Exemplu de graf neorientat
Atunci matricea de adiacen ataat grafului este:
A =
_
_
_
_
_
0 1 0 1
1 0 1 1
0 1 0 1
1 1 1 0
_
_
_
_
_
b. Reprezentarea cu ajutorul listelor de adiacen
Pentru a elimina dezavantajele reprezentrii grafurilor neorientate cu ajutorul ma-
tricelor de adiacen putem folosi o metod bazat pe reprezentarea cu liste nlnuite,
numit reprezentare cu liste de adiacen.
4.6. Grafuri 159
Lista de adiacen pentru un vrf i este o list simplu nlnuit a tuturor nodurilor
adiacente cu i. n acest fel reprezentarea grafului orientat G = (X, U), se face cu o
tabel n dimensional numit CAP, elementul CAP[i] reprezentnd un pointer ctre
capul listei de adiacen al vrfului i.
Exemplul 4.6.4. Reprezentarea grafului din Figura 4.24 cu ajutorul listelor de adi-
acen:
CAP
4 2
1
4
3
2
3 2 1
4
2
4 3 1
Figura 4.25: Reprezentarea grafului orientat din Figura 4.24 cu ajutorul listelor de
adiacen
4.6.3 Grafuri planare
Pentru a reprezenta unele structuri geometrice n plan sau n spaiu se folosete o
categorie special de structuri de date: grafuri planare.
Deniia 4.6.9. Un graf G este planar dac este posibil s e reprezentat pe un
plan astfel nct vrfurile s e distincte, muchiile curbe simple i dou muchii s nu
se intersecteze dect la extremitile lor (dac sunt adiacente).
Reprezentarea grafului conform cu condiiile impuse se numete graf planar topo-
logic i se noteaz tot prin G. Nu se consider distincte dou grafuri planare topologice
dac le putem face s coincid prin deformarea elastic a planului.
Deniia 4.6.10. O fa a unui graf planar este o regiune a planului delimitat de
muchii, care are proprietatea c orice dou puncte din aceast regiune pot unite
printr-o curb simpl care nu ntlnete nici muchii i nici vrfuri.
160 4. Structuri de date
Deniia 4.6.11. Frontiera unei fee este mulimea muchiilor care ating faa respec-
tiv. Dou fee sunt adiacente dac frontierele lor au cel puin o muchie comun.
ntr-un graf topologic, frontiera unei fee este format din unul sau mai multe ci-
cluri elementare disjuncte, din muchii suspendate sau care unesc dou cicluri disjuncte
(istmuri).
Deniia 4.6.12. Conturul unei fee este conturul ciclurilor elementare care conin
n interiorul lor toate celelalte muchii ale frontierei.
Exist ntotdeauna o fa innit i care are frontier, dar nu are contur; toate
celelalte fee sunt nite i admit un contur.
Teorema 4.6.1. ntr-un graf planar topologic conex cu n vrfuri, m muchii i f fee
avem relaia:
n m+f = 2.
Demonstraie [Tom, 1981]. Dac f = 1 atunci m = n 1 pentru un arbore (lema
4.6.1), deci relaia este adevrat.
Presupunem armaia adevrat pentru orice graf planar conex cu f 1 fee, i s
considerm un graf planar conex cu f fee. Fie (x, y) o muchie a unui ciclu; aceasta
se a pe frontiera a dou fee S i T. Dac eliminm muchia (x, y) se obine un graf
planar conex cu n

= n vrfuri, m

= m1 muchii i f

= f 1 fee. Conform ipotezei


de inducie n

+f

= n1 m+1 +f = 2, de unde obinem c nm+f = 2.


Corolar 4.6.1. n orice graf planar topologic conex cu n vrfuri, m muchii i f fee
avem:
(i) n 2m/3; m 3f 6; n 2f 4 (dac ecare vrf are gradul cel puin trei)
(ii) f 2m/3; m 3n 6; f 2n 4 (dac graful are cel puin dou muchii)
Demonstraie. (i) Din ecare vrf pleac cel puin trei muchii, i ecare muchie
unete dou vrfuri; rezult 3n 2m. Celelalte dou inegaliti rezult prin simpl
nlocuire.
(ii) Dac m = 2 atunci f = 1 i n = 3. Dac f = 1 i m > 2 atunci n = m + 1.
Dac f 2 atunci ecare fa are cel puin trei laturi (muchii), i o muchie este
comun la cel mult dou fee; rezult 3f 2m. Celelalte dou inegaliti rezult prin
simpl nlocuire.
S considerm n spaiul tridimensional un poliedru convex cu n vrfuri, m muchii
i f fee. Putem s-l reprezentm pe o sfer astfel nct dou muchii s nu se inter-
secteze dect la extremiti. Efectund o proiecie stereograc al crei centru s e
n mijlocul unei fee, poliedrul se poate reprezenta pe un plan. Graful ind planar, se
obine relaia lui Euler n m+f = 2.
Capitolul 5
Tehnici de cutare
5.1 Introducere n tehnicile de cutare
O operaie fundamental intrinsec pentru un numr mare de probleme de calcul
este cutarea: recuperarea unei buci de informaii dintr-o mulime de informaii
stocate anterior.
De obicei, informaia este divizat in mai multe nregistrri , ecare nregistrare
are o cheie care este folosit n procesul de cutare. Obiectivul cutrii este de a
gsi toate nregistrrile care au chei identice cu cea care este cheia de cutare. Scopul
cutrii este de a accesa informaiile din nregistrri pentru procesare.
n cazul procesului de cutare avem diferite programe care sunt cunoscute pre-
tutindeni i utilizate frecvent, deci merit s studiem o serie de metode mai detaliat.
Vom ncepe cu studierea unor metode elementare care sunt utilizate cu succes pentru
tabele de dimensiuni mici i n alte situaii speciale i ilustreaz fundamental tehnicile
exploatate de ctre metode mult mai avansate. Vom studia metodele care stocheaz
nregistrri n liste, care sunt cutate ori prin compararea cheilor sau prin indexarea
valorii cheii i vom studia metode fundamentale care construiesc structuri denite de
valoarea cheii.
Cutarea reprezint operaiunea care dureaz cel mai mult n majoritatea pro-
gramelor de prelucrare, iar nlocuirea unei metode mai proaste de cutare cu una
mai bun conduce deseori la o cretere substanial n viteza de prelucrare.
Deci scopul acestui capitol este s prezinte ntr-o manier accesibil pentru pro-
gramatori cteva tehnici de cutare cum ar : cutarea secvenial, cutarea binar,
arbori binari de cutare si tabele de dispersie (hash) precum o serie de tehnici de
rezolvare a coliziunilor [Kor, 1988].
161
162 5. Tehnici de cutare
n locul descrierii la nivel conceptual a soluiilor unor probleme de programare,
folosind exclusiv instrumente "articiale" gen Pseudocod, care s e adaptate mai
mult sau mai puin claselor de algoritmi discutai, prezentarea celor mai performante
soluii teoretice este completat de descrierea metodelor i mecanismul de imple-
mentare a lor, folosind limbajul de programare Pascal.
5.1.1 Cutare secvenial
5.1.1.1 Descrierea general a metodei
Cea mai simpl metod de cutare este cutarea secvenial. O metod simpl
de stocare a informaiei este stocarea nregistrrilor ntr-o tabel. Cnd o nou n-
registrare este inserat, acesta se adaug n poziia dorit, cnd trebuie efectuat o
cutare, tabela este parcurs secvenial.
Cutarea secvenial este cea mai simpl metod de cutare a unei nregistrri
ntr-o tabel neordonat, ntr-un mod secvenial, pn cnd nregistrarea dorit este
gsit.
n multe aplicaii este nevoie ca s extindem programul pentru ca s putem lucra
cu nregistrri si chei mai complicate, dar acesta nu va afecta fundamental algoritmul
de cutare.
Alte operaii posibile ntr-o tabel, n afar de operaia de cutare, sunt ope-
raiile de inserare i tergere. Datele pot inserate sau terse la nceputul tabelei,
la sfritul tabelei i n interiorul tabelei.
Un algoritm de inserare la sfritul tabelei, implementat n Pascal, este prezentat
mai jos:
Procedure INSERARE;
begin
write(Introducei elementul pe care dorii s-l inserai:);
readln(g);
T[nr+1]:=g; { nr numrul de elemente din tablou }
end;
n cazul operaiei de tergere la nceput, primul element din tabel este ters, iar
celelalte elemente se vor translata ecare cu o poziie n sus n tabel. Un algoritm
general pentru cutare secvenial este prezentat mai jos.
Avem un vector neordonat T avnd MAX (MAX >= 1) elemente. Acest algoritm
caut n vectorul T elementul particular avnd valoarea X. Funcia returneaz indexul
elementului dac cutarea este cu succes, altfel returneaz 0.
Secvena de instruciuni n Pseudocod este:
5.1. Introducere n tehnicile de cutare 163
k := 1;
CTTIMP k <= MAX EXECUT
DAC T[k] = X
ATUNCI
@ returneaz k; {cutare cu succes}
EXIT;
ALTFEL
k := k + 1;
SFDAC
SFCT
@ returneaz 0; {cutare cu insucces}
Primul pas al algoritmului iniializeaz valoarea variabilei k, cu ajutorul creia
parcurgem tabela. n pasul al doilea se face o cutare secvenial. Dac variabila
k depete capacitatea maxim MAX atunci avem cutare fr succes (nu s-a gsit
un element al tabelei cu valoarea X), altfel avem cutare cu succes i variabila k va
conine indexul nregistrrii cutate.
Implementarea n PASCAL a algoritmului de cutare secvenial este:
Exemplul 5.1.1.
Function CAUTARE _SECVENTIALA ( T , j , X ) : integer ;
Begin
k := 1 ; { k - elementul cu care parcurgem tabela }
OK := false
while (not OK) and (k <= j) do {j - numrul de elemente din tabela T}
begin
if T [ k ] = X then { X cheia cutat }
begin
OK := true ;
CAUTARE_SECVENTIALA := k ;
end ;
exit
else
k := k + 1 ;
end;
CAUTARE_SECVENTIALA := 0 ;
end ;
164 5. Tehnici de cutare
Performana unei metode de cutare se msoar prin numrarea comparaiilor
cheii pn ce este gsit o nregistrare particular. Sunt dou cazuri importante, i
anume [Aho, 1987]:
Cazul general (Average Length of Search - ALOS)
Cazul cel mai nefavorabil (Worst Length of Search - WLOS) .
Cutarea secvenial (implementare cu ajutorul unui vector de dimensiune n), necesit
n cazul cel mai nefavorabil (cutare fr succes) n+1 operaii de comparaie, iar
n cazul general, avem (n+1)/2 operaii de comparaie pentru o cutare cu succes.
Formula de calcul a performanelor metodei de cutare n cazul general ALOS ,
este exprimat prin formula [Tre, 1984]:
ALOS =
n

i=1
p
i
nr
i
(5.1)
unde p
i
reprezint probabilitatea ca informaia a-i-a s e cutat, iar nr
i
reprezint
numrul de operaii necesar accesrii informaiei a-i-a. Probabilitatea ca o dat s
e cutat poate exprimat prin raportul:
p
i
=
nr_de_cautari_al_datei_i
nr_total_de_cautari
(5.2)
Pentru o cutare cu succes, dac presupunem c probabilitatea de cutare a unei
nregistrri particulare este aceeai cu probabilitatea de cutare a altor nregistrri,
atunci numrul general de comparaii este:
ALOS =
n

i=1
1
n
i =
1 + 2 +. . . n
n
=
n(n + 1)
2
n
=
n + 1
2
(5.3)
n cazul n care probabilitatea de accesare a datelor din tabel nu este echiprob-
abil, atunci cea mai ecient metod de organizare a datelor este cea n ordine
descresctoare a probabilitilor de cutare, datele cele mai probabile a cutate
ind dispuse la nceputul tabelei. S dovedim aceast armaie:
e datele organizate ntr-o tabel n ordinea descresctoare a probabilitilor de
cutare, i anume:
Data
1
Data
2
. . . . . . . . . . . . .. Data
i
. . . . . . . . . . . . .. Data
n
5.1. Introducere n tehnicile de cutare 165
astfel nct:
p
1
> p
2
> . . . > p
i
. . . p
n
(5.4)
Pentru aceast organizare a datelor n tabel avem performana:
ALOS
1
=
n

i=1
p
i
nr
i
=
n

i=1
p
i
i = 1 p
1
+ 2 p
2
+. . . +i p
i
+. . . +j p
j
+. . . +n p
n
unde i < j. S presupunem c exist o alt organizare a datelor, unde acestea nu sunt
organizate n tabel n ordinea descresctoare a probabilitilor de cutare (5.4), i s
msurm performana ALOS a algoritmului de cutare. Este sucient s presupunem
c exist o simpl permutare a datelor, i anume c avem permutate Data
i
cu Data
j
n tabel. n aceast situaie, performana algoritmului de cutare este:
ALOS
2
=
n

i=1
p
i
nr
i
=
n

i=1
p
i
i = 1 p
1
+ 2 p
2
+. . . +i p
j
+. . . +j p
i
+. . . +n p
n
S comparm cele dou performane:
ALOS
1
ALOS
2
= i p
i
+j p
j
i p
j
j p
i
= p
i
(i j) +p
j
(j i)(i j) < 0
deoarece p
i
> p
j
i i < j.
Concluzia este evident, organizarea datelor ntr-o tabel pentru a avea cea mai
bun performan media a operaiei de cutare este conform cu (5.4), adic datele
trebuie organizate n ordine descresctoare a probabilitii de cutare.
5.1.1.2 Probleme rezolvate pentru cutare secvenial
Exemplul 5.1.2. Problema cutrii unei nregistrri particulare ntr-o tabel
Fiind dat un tablou cu o capacitate de maxim MAX nregistrri posibile (nreg-
istrri de tip numr ntreg ), se cere implementarea n limbajul Pascal a unui algo-
ritm algoritmi care s realizeze urmtoarele operaii: inserare, cutare (secvenial)
i tergere n tablou.
Program cautare_in_tabel ;
const
MAX=100;
type
tablou = array [1..MAX] of integer;
var
T : tablou ;
d , nr , k , g , i , j : integer ;
166 5. Tehnici de cutare
a : char ;
Procedure TESTARE ;
begin
if nr > MAX then begin
{ nr numrul elementelor din tabel }
{ MAX numrul maxim de elemente }
write ( Depire capacitate ) ;
delay ( 4000 ) ;
halt ;
end ;
end ;
Procedure INSERARE ;
begin
write ( Introducei elementul de inserat: ) ;
readln ( g ) ; { g elementul care se nsereaz }
for k := nr downto 1 do
T[ k+1 ] := T [ k ] ;
T[ 1 ] := g ;
writeln ( Tabloul este: ) ;
for i := 1 to (nr + 1) do
writeln ( T[ , i , ]= , T[ i ] ) ;
readln ;
end ;
Procedure STERGERE ;
begin
write ( Introducei poziia elementului de sters: ) ;
readln ( d ) ; { d reprezint poziia elementului care va ters }
for k := d+1 to nr do
T [ k-1 ] := T [ k ] ;
writeln ( Tabloul este : ) ;
for i := 1 to ( nr-1 ) do
writeln ( T [ , i , ]= , T [ i ] ) ;
readln ;
end ;
Procedure CAUTARE ;
var
ok : boolean ;
5.1. Introducere n tehnicile de cutare 167
h : integer ;
begin
write ( Introducei elementul cutat : ) ;
readln ( h ) ; { h elementul cutat }
ok := false ;
for i := 1 to nr do
begin
if T[ i ] = h then
begin
ok := true;
writeln ( Elementul cutat se a pe poziia : , i ) ;
end ;
end ;
if not ok then
writeln ( Elementul cutat nu exist n tablou ! ) ;
readkey ;
end ;
BEGIN
clrscr ;
write ( Introducei nr. de elemente dorite : ) ;
readln ( nr ) ;
TESTARE ;
for i := 1 to nr do
begin
write ( T[ , i , ] = ) ;
readln ( T[ i ] ) ;
end ;
repeat
clrscr ;
writeln ( Apsai tasta dorit : ) ;
writeln ( 0 : Pentru nserare n tablou ) ;
writeln ( 1 : tergere n tablou ) ;
writeln ( 2 : Cutare n tablou ) ;
writeln ( Pentru ieire din program apsai tasta Esc ) ;
a := readkey ;
case a of
0 : INSERARE ;
168 5. Tehnici de cutare
1 : STERGERE;
2 : CAUTARE ;
end ;
until a = # 27 ;
END.
Exemplul 5.1.3. Problema elementelor pozitive, negative si nenule
Numrai elementele pozitive, negative i nenule ale unei liste ntr-o funcie care
dup apelare, returneaz un pointer la un vector cu trei componente, ce stocheaz
rezultatele parcurgerii listei.
Program numara ;
type
plista = lista ;
lista =record
b : integer ;
paue : plista ;
end ;
vec = array [ 1..3 ] of byte ;
pv = vec ;
var
cp1 : plista ;
i, n : integer ;
vect : vec ;
pvec : pv ;
Function creare ( n:integer ) : plista ;
var
prad : plista ;
begin
if n = 0 then
creare := NIL
else
begin
n := n-1;
write ( Dati elementul : ) ;
new (prad) ;
readln (prad .b) ;
prad .paue := creare (n) ;
5.1. Introducere n tehnicile de cutare 169
creare := prad ;
end ;
end ;
Function numr (p1 : plista) : pv ;
var
plucru : pv ;
begin
plucru := vect ;
for i := 1 to 3 do
plucru [ i ] := 0 ;
while p1 < > NIL do
begin
if p1 . b > 0 then
plucru [ 1 ] := plucru [ 1 ] + 1
else
if p1 .b < 0 then
plucru [ 2 ] := plucru [ 2 ] + 1
else
plucru [ 3 ] := plucru [ 3 ] + 1 ;
p1 := p1 .paue ;
end ;
numr := plucru ;
end ;
BEGIN
write ( Introduceti numrul de elemente ale listei : ) ;
readln (n) ;
cp1 := creare (n) ;
pvec := numr (cp1) ;
writeln ;
END.
5.1.1.3 Probleme propuse
1. Dac toate cheile de cutare sunt echiprobabile, care este deviaia standard a
numrului de comparaii efectuate ntr-o cutare secvenial cu succes ntr-un
tabel cu N nregistrri?
2. Presupunem c dorii s cutai ntr-un ier voluminos, nu dup criteriul egali-
tii, ci pentru a gsi 1000 de nregistrri cele mai apropiate unei chei date,
170 5. Tehnici de cutare
n sensul c aceste 1000 de nregistrri au cea mai mic valoare a lui d (Ki,K)
pentru o funcie d de distan dat. Care structur de date este cea mai adecvat
pentru o asemenea cutare secvenial ?
3. Fiind date dou succesiuni < X
1
, X
2
, . . ., X
n
> i < Y
1
, Y
2
, . . . , Y
n
> de numere
reale, care permutare a
1
a
2
. . . a
n
a indiciilor va determina valoarea maxim
al lui (X
i
Y
a
i
)? Dar valoarea minim?
4. Un programator dorete s testeze dac n condiii date snt sau nu simultan
ndeplinite. (De exemplu, el poate dori s testeze dac simultan este adevrat
ca x > 0 si y < z z, dar nu este evident care dintre condiii trebuie testat
prima). S presupunem c sunt necesare T
i
uniti de timp pentru testarea
condiiei i i c aceast condiie se adeverete cu probabilitatea P
i
, independent
de rezultatul celorlalte teste de condiii. n care ordine trebuie s se execute
testarea condiiilor?
5. Fiind dat un text cu maxim 80 de caractere ce se termin cu caracterul $, s se
scrie un program care s aeze textul n ordine invers.
6. Dac X este un vector cu n componente reale, scriei secvene de instruciuni
pentru a obine urmtoarele transformri (fr a folosi un vector suplimentar):
a) (X
1
, X
2
, . . . , X
n
) (X
n
, X
1
, X
2
, . . . , X
n1
)
b) (X
1
, X
2
, . . . , X
n
) (X
n
, X
n1
, X
n2
, . . . , X
2
, X
1
)
c) (X
1
, X
2
, . . . , X
n
) (X
i
1
, X
i
2
, . . . , X
i
n
)
astfel nct X
i
1
< X
i
2
< . . . < X
i
n
iar 1 <= i
k
<= n; 1 <= k <= n.
d ) Pe primele poziii s apar elementele negative in aceeai ordine ca n irul
iniial.
7. Se consider un text ce conine litere mari, litere mici, semnele de punctuaie:
, ; . ; : ; ! ; ? ; - ; _ ; i se termin cu caracterul $. S se aeze numrul
de apariii ale ecrui caracter, precum i numrul de caractere diferite ntlnite
n text. Se presupune c $ nu este un caracter al textului.
8. Fie E un numr natural cu n cifre memorate ntr-un vector de dimensiune n
din domeniul 0 . . . 9. S se verice dac E este un numr divizibil cu:
a) 2 ; b) 5 ; c) 4 ; d) 3 ; e) 9 ; f) 7 ; g)11 ; h) 8 ; i) 25 ; j) 125 ;
k) 13 ; l) 27 ; m) 37 ; n) 6 ; o) 15.
9. S se aeze toate numerele de n cifre care adunate cu rsturnatul lor dau un
ptrat perfect.
5.1. Introducere n tehnicile de cutare 171
10. S se implementeze un algoritm care rearanjeaz toate elementele dintr-un
tablou unidimensional, astfel nct toate valorile negative vor precede pe cele
pozitive. S se utilizeze un numr minim de interschimbri.
11. S se implementeze un algoritm care pentru dou numere ntregi cu n cifre me-
morate vectorial s determine suma, produsul, ctul i restul mpririi primului
numr la al doilea numr. Rezultatele se vor obine sub forma vectorial.
5.1.2 Cutare binar
5.1.2.1 Descrierea general a metodei
O alt metod relativ simpl de accesare a unei tabele este metoda cutrii binare.
Organizarea datelor n aceast tabel se bazeaz pe ordonarea liniar a cheilor (de
exemplu, n ordine alfabetic sau ordine numeric cresctoare). O metod potrivit
pentru ordonarea datelor este sortarea, despre care vom vorbi ntr-un capitol ulterior.
O cutare pentru o nregistrare cu o anumit valoare a cheii este asemntoare
cu cutarea unui nume ntr-o agend de telefoane. Este localizat cu aproximaie
nregistrarea din mijlocul tabelei, este comparat cheia nregistrrii din mijloc cu
cheia nregistrrii cutate. Dac cheia cutat este mai mare dect valoarea cheii
din mijloc atunci procedura se repet n jumtatea de interes a tabelei, pn cnd
nregistrarea dorit este gsit sau intervalul de cutare este gol, ceea ce semnic
lipsa cheii cutate.
n gura 5.1 avem un exemplu de cutare binar a cheii m aat ntr-o tabel
construit prin inserarea cheilor a s e a r c h i n g e x a m p l e [Tre, 1984]. Intervalul
de chei este njumtit la ecare pas, deci numai patru comparaii snt necesare n
acest caz.
x s r p n m l i h g e e e c a a a
x s r p n m l i
m l i
m
Figura 5.1: Exemplu de cutare binar
172 5. Tehnici de cutare
Operaia de inserare (metoda inserrii binare ) realizeaz n ecare din cei N-1
pai ai si nserarea celei de a i a nregistrri din tabloul iniial n irul deja sortat
al precedentelor i -1 nregistrri .
Determinarea poziiei de inserare se face prin cutare binar, folosindu-se faptul
c nregistrrile precedente sunt deja sortate i reducndu-se astfel numrul mediu de
comparaii necesare de la i/2 la log
2
i.
Operaia de tergere presupune ca elementele din tablou, aate naintea elemen-
tului care va ters, vor rmne pe loc, poziiile lor nu se schimb, elementele care
se a dup elementul care va ters, vor translatate cu o poziie.
5.1.2.2 Descrierea algoritmului de cutare n Pseudocod
Un algoritm pentru o astfel de procedur de cutare este prezentat n rndurile ur-
mtoare.
Avem un vector K cu N elemente ordonate cresctor, acest algoritm face o cutare
pentru un element cu valoarea X. Variabilele LOW, MIDDLE i HIGH noteaz
limita inferioar, mijlocul i limita superioar a intervalului de cutare. Funcia
de cutare returneaz indexul elementului cutat, dac avem o cutare cu succes, altfel
returneaz valoarea 0.
LOW := 1 {Pasul 1}
HIGH := N
CTTIMP LOW <= HIGH EXECUT {Pasul 2}
MIDDLE := [(LOW +HIGH ) / 2 ] {Pasul 3}
DAC X < K [MIDDLE] {Pasul 4}
ATUNCI HIGH := MIDDLE-1
ALTFEL DAC X > K [MIDDLE]
ATUNCI LOW := MIDDLE + 1
ALTFEL {Cutare cu succes }
@returneaz MIDDLE
SFDAC
SFDAC
SFCT
@returneaz 0 {Cutare fr succes } {Pasul 5}
Pasul 1 iniializeaz variabilele LOW i HIGH, pasul 3 calculeaz valoarea vari-
abilei MIDDLE, care este mijlocul tabelei. Pasul 4 face comparaiile ntre cheia de
cutat i valorile limit i returneaz cheia cutat dac este gsit. Pasul 5 returneaz
valoarea 0, adic cutare fr succes.
5.1. Introducere n tehnicile de cutare 173
Cutarea binar poate fcut i n mod recursiv. La un astfel de algoritm este
important timpul de execuie (timpul de cutare) i spaiul folosit. Descrierea
algoritmului de cutare binar (n mod recursiv) n Pseudocod este prezentat n
continuare.
Avem un subinterval a crei limite snt P si Q, i un vector K. Acest algoritm
recursiv caut un element dat al crei valoare este stocat n variabila X , MIDDLE
i LOC sunt variabile de tip ntreg.
FUNCTIA CAUTARE_BINARA _R (P , Q , K , X ) ESTE:
DAC P > Q
ATUNCI
LOC := 0;
ALTFEL
MIDDLE := [( P + Q )/ 2 ];
DAC X < K [MIDDLE ]
ATUNCI
LOC := CAUTARE_BINARA _R (P,MIDDLE-1,K,X );
ALTFEL
DAC X > K [MIDDLE ]
ATUNCI
LOC:=CAUTARE_BINARA _R (MIDDLE+1,Q,K,X );
ALTFEL
LOC := MIDDLE;
SFDAC
SFDAC
SFDAC
SF-CAUTARE_BINARA;
Exemplul 5.1.4. Implementarea algoritmului de cutare binar n Pascal.
Function CAUTARE _BINARA ( K , LOW,HIGH ,MIDDLE, X ) : integer;
Begin
LOW := 1 ;
HIGH := N;
repeat
MIDDLE := (LOW + HIGH) / 2 ;
if X < K[MIDDLE] then
begin
HIGH := MIDDLE-1
174 5. Tehnici de cutare
else if X > K[MIDDLE] then do
LOW := MIDDLE + 1
else begin
writeln ( Cutare cu succes ! ) ;
writeln ( Poziia : , MIDDLE );
exit ;
end ;
end ;
until LOW <= HIGH;
writeln ( Cutare fr succes ! ) ;
end;
5.1.2.3 Performana algoritmului de cutare
Timpul de cutare (execuie), T(n) depinde de numrul de comparaii efectuate, care
depind la rndul lor de poziia informaiei cutate X. n cel mai bun caz, informaia
cutat este poziionat n locaia
_
n + 1
2
_
(am notat cu [ ] funcia parte ntreag). n
aceast situaie este necesar doar o singur operaie de comparaie, deci T(n) = O(1).
Cutarea binar nu folosete nici odat mai mult de lg N + 1 comparaii pentru
cutarea cu succes, ct i pentru cutarea fr succes ([Aho, 1987]).
n procesul de cutare binar recursiv, cheia cutat este gsit n maximum
log N comparaii care este un ctig deosebit faa de cele N/2 comparaii ale cutrii
secveniale.
Pentru a determina timpul de cutare n cazul operaiei de cutare binar, vom
considera c toate datele sunt echiprobabile. Pentru a simplica analiza, vom pre-
supune c dimensionalitatea datelor este de forma n = 2
k
1. Atunci k = log
2
(n+1).
Aceast ipotez nu distruge generalitatea argumentaiei, cci putem oricnd com-
pleta o structur de date cu elemente care nu sunt cutabile, ca s o aducem la forma
2
k
1. Oricum, timpul de execuie al structurii de date originale va mai mic sau
egal dect a structurii de date aduse la forma n = 2
k
1.
S notm cu S
i
, numrul de elemente pentru care algoritmul de cutare binar
efectueaz un numr de i operaii (comparaii). Avem:
S
1
= 1 = 2
0
; S
2
= 2 = 2
1
; S
3
= 4 = 2
2
; . . . ; S
i
= 2
i1
, i k
5.1. Introducere n tehnicile de cutare 175
Aplicnd formula (5.1) vom avea:
T(n) =
k

i=1
p
i
d
i
=
k

i=1
S
i
n
i =
1
n
k

i=1
i 2
i1
=
1
n
k

i=1
i (2
i
2
i1
) =
=
1
n
_
k

i=1
i 2
i

k1

i=0
(i + 1) 2
i
_
=
1
n
_
k

i=1
i 2
i

k1

i=1
i 2
i

k1

i=0
2
i
_
=
=
1
n
(k 2
k
2
k
+ 1) =
1
n
[(k 1) (2
k
1) +k] = (k 1) +
k
n
=
= log
2
(n + 1) 1 +
log
2
(n + 1)
n
=
_
1 +
1
n
_
log
2
(n + 1) 1 log
2
n
Putem considera c avem: T(n) = O(log
2
n), att pentru cazul general ct i pentru
cel mai nefarorabil caz.
n caracterizarea acestui algoritm pe lng timpul de execuie este important i
spaiul necesar pentru memorarea datelor. Pentru algoritmul de cutare binar
analiza spaiului este mai interesant dac presupunem c vectorul este transmis ca
i parametru prin valoare [Sed, 1988]. Acesta nseamn c pentru ecare accesare a
funciei Cutare_Binar_R are loc o stocare local diferit pentru vector (vectorul
are mai multe copii). Deci spaiul pentru un apel al rutinei este prorional cu O(n).
Dup cum am vzut mai sus, n cazul general sau cel mai nefavorabil avem nevoie de
O(log
2
n) operaii de cutare , adic n nal avem nevoie de un spaiu de memorie
proporional cu O(nlog
2
n).
Observaie. Tehnica de cutare binar are i unele proprieti nedorite. Inserarea
unei noi nregistrri impune ca o serie de nregistrri existente n tabel s e mutate
zic pentru a pstra ordinea cresctoare. O situaie similar este prezent i n cazul
procesului de tergere .
La aceast metod timpul necesar operaiei de tergere ocup o proporie mare
din timpul de cutare. Cutarea binar este potrivit pentru aplicaii n care sunt
efectuate puine operaii de inserare sau tergere.
5.1.2.4 Probleme rezolvate pentru cutarea binar
Exemplul 5.1.5. Problema cutrii elementelor comune a dou iruri de numere
[Tud, 1993].
Aceast problem construiete vectorul elementelor comune a doi vectori (a, b).
Se va parcurge secvenial vectorul a, i ecare element care este gsit i n vectorul b
va memorat ntr-un vector nou c construit de ctre subprogram .
Acest program funcioneaz att pentru vectori ordonai cresctor, ct i pentru
vectori ordonai descresctor.
176 5. Tehnici de cutare
Program elemente_comune ;
const
max_elem = 10 ;
type
cazuri = ( constant , cresc , desc ,neord ) ;
val_indice = 1 .. max_elem ;
vector = array [val_indice ] of integer ;
var
a , b , c : vector ;
na , nb , ic , indice : val_indice ;
tip : cazuri ;
Procedure citete vector ( var x : vector ; varnumr : val_indice ; car : char ) ;
var
i : integer ;
begin
i := 0 ;
repeat
i := i + 1 ;
write ( , car , [ , I :2 , ] = ) ; read (x [ i ]) ;
if ( i mod 5 ) = 0
then writeln ;
until ( x[ i ] < 0 ) or ( i > = max_elem ) ;
if x [ i ] < 0
then numr : = i 1
else
numr : = i ;
writeln ;
end
end ;
Procedure aeaz ( x : vector ; numr : val_indice ) ;
var
i : val_indice ;
begin
for i : = 1 to numr do
begin
write ( x [ , I : 2 , ] = , x [ I ] ) ;
If ( i mod 5 ) = 0
5.1. Introducere n tehnicile de cutare 177
then writeln ;
end
end ;
function gasit ( x : vector ; numr : val_indice ; elem : integer ) : boolean ;
var
i : integer ;
begin
i := 1 ;
while ( x [ i ] <> elem ) and ( i < numr ) do
i := i + 1 ;
gsit := x [ i ] = elem
end ;
function tip_ord ( x : vector ; numr : val_indice ) : cazuri;
var
ord_cresc , odr_desc : boolean ;
i : integer ;
begin
ord_cresc := true ;
ord_desc := true ;
i := 0 ;
while (ord_cresc or ord_desc ) and ( I < numr 1 ) do
begin
i := i+ 1 ;
if x [ i ] > x [ i + 1 ]
then ord_cresc := false ;
if x [ i ] < x [ i + 1 ]
then ord_desc := false ;
End ;
if ord_cresc and ord_desc
then tip_ord := constant { ir constant }
else
if ord cresc
then tip_ord :=cresc { ir cresctor }
else
if ord_desc
then tip_ord := desc {ir descresctor }
else tip_ord := neord ( ir neordonat }
178 5. Tehnici de cutare
end;
Function cautare_bin ( x : vector ; numr : val_indice ; valoare : integer ) :
boolean ;
var
inferior , superior , mijloc : integer ;
begin
inferior := 1 ;
superior := numr ;
mijloc := ( inferior + superior) div 2 ;
while ( valoare <> x [ mijloc ] ) and ( ( superior inferior ) > 1 ) do
begin
if ( tip = cresc ) and ( valoare < x [ mijloc ] ) or
( tip = desc ) and ( valoare > x [ mijloc ] )
then superior := mijloc
else inferior := mijloc ;
mijloc := ( inferior + superior ) div 2 ;
end ;
if x [ mijloc ] <> valoare
then
begin
if x [ superior ] = valoare
then mijloc := superior ;
if x [ inferior ] = valoare
then mijloc := inferior
end;
cutare_bin := x [ mijloc ] = valoare
end ;
Procedure construieste (x ,y : vector ; nx , ny : val_indice ; var numr : val_indice);
Procedure memoreaz ;
begin
if ( not gsit (c , numr , x [ indice ])) or ( numr = 0 )
then
begin
Numr := numr + 1 ;
c [ numr ] := x [ indice ]
end
end;
5.1. Introducere n tehnicile de cutare 179
begin
Numr := 0 ;
for indice := 1 to nx do
case tip of
constant : if x [ indice ] = y [ 1 ]
then memoreaz ;
desc , cresc : if cutare _bin ( y , ny , x [ indice ] )
then memoreaz ;
neord : if gsit ( y, ny , x [ indice ] )
then memoreaz
end;
end;
{ program principal }
BEGIN
citete vector ( a , na , a );
citete vector ( b , nb , b );
tip := tip_ord ( a , na ) ;
if tip = neord ;
then
begin
tip := tip_ord ( b , nb );
construiete ( a , b , na , nb , ic )
end
else
construiete ( b , a , nb , na , ic );
writeln ;
if ic <> 0
then
begin
writeln ( Elementele comune snt : ) ;
writeln ;
aeaza ( c , ic );
end
else
writeln ( Nu exist elemente comune );
END.
Exemplul 5.1.6. Cutare binar ntr-un ir dat.
180 5. Tehnici de cutare
Se citete un ir cu un numr dat de componente numere reale i se introduce apoi
de la tastatur o valoare real. S se stabileasc dac valoarea dat se gsete sau nu
n ir.
Program cutare_binar ;
var
a : array [ 1.. 1000 ] of real ;
x : real ;
i , n , margs , margd , jum : integer ;
este : boolean ;
BEGIN
write ( Nr . elemente = ) ;
readln ( n) ;
write ( Introducei elementele cu spaii sau enter : ) ;
for i := 1 to n do read ( a [ i ] ) ; readln ;
write ( Numrul cutat = ) ;readln ( x ) ;
if ( x = a [1] ) or ( x = a [n] then writeln ( este ) ;
else
begin
margs := 1 ; margd := n ;
{ marginile stnga / dreapta ale intervalului }
este := false ;
while ( margd - margs > 1 ) and not este do
begin
jum := trunc ( (margs + margd ) / 2 ) ;
{ mijlocul intervalului }
if a [jum] = x then este := true
else if x > a [jum] then margs := jum
else margd := jum
end ;
if este = true then writeln ( este )
else writeln ( nu este )
end ;
readln ;
END.
5.2. Arbori de cutare 181
5.1.2.5 Probleme propuse
1. Dac o operaie de cutare ce folosete algoritmul de cutare secvenial necesit
exact 638 de operaii, ct va dura operaia de cutare dac folosete algoritmul
de cutare binar?
2. Pentru ce valori al lui N algoritmul de cutare binar este, n medie, mai lent
dect algoritmul de cutare secvenial, presupunnd o cutare cu succes?
3. Problema 2 sugereaz c ar mai bine s dispunem de o metod hibrid,
adic s trecem de la cutare binar la cutare secvenial n momentul n care
intervalul rmas are o lungime mai mic dect o anumit valoare judicios aleas.
Scriei un algoritm ecient pentru o asemenea cutare i determinai valoarea
optim de comutare.
4. ListaOrdonata este un tablou de tip ntreg cu 10 poziii. Cum ar arta tabloul
ListaOrdinara n cazul n care ar conine urmtoare valori, citite dintr-un ier:
14, 27, 95, 12, 26, 5, 33, 15, 9, 99 i elementele ar sortate n ordine cresctoare?
ListaOrdonata
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10]
5.2 Arbori de cutare
5.2.1 Arbore binar de cutare ABC
5.2.1.1 Descrierea general a arborelui binar de cutare
ntr-o structur de date de tip arbore de cutare, informaiile, sunt structurate pe
nivele, pe primul nivel, numit nivel 0, exist un singur element numit rdcin, de
care sunt legate mai multe elemente numite i care formeaz nivelul 1; de acestea
sunt legate elementele de pe nivelul 2, .a.m.d. (vezi gura 5.2).
Un arbore este compus din elementele numite noduri sau vrfuri i legturile
dintre acestea. Dup cum am vzut, cea mai des utilizat form de organizare a unui
arbore binar este urmtoarea:
Cheia nodului u stnga < Cheia nodului tat < Cheia nodului u stnga (5.5)
Utiliznd formula de mai sus se obin arbori binari speciali, utilizai pentru orga-
nizarea i cutarea datelor, numii arbori binari de cutare ABC.
182 5. Tehnici de cutare
Un nod situat pe un anumit nivel este nod tat pentru nodurile legate de el,
situate pe nivelul urmtor, acestea reprezentnd i si. Arborii, ca structuri de date
dinamice, au foarte multe aplicaii n informatic. Structurile arborescente sunt foarte
des utilizate pentru memorarea i regsirea rapid a unor informaii. Informaiile
sunt organizate dup un cmp numit cheie, ales de programator, care servete la
identicarea datelor stocate n structura arborescent. De exemplu, dac datele sunt
datele relative la studenii unei faculti, atunci cheia poate aleas ca ind numele
i prenumele studentului. Cheile trebuie alese n aa fel nct s nu apar chei duble.
n exemplul nostru relativ la studenii unei faculti, poate c ar mai bine s evitm
posibilitatea existenei unor chei duble, acelai nume i prenume, prin introducerea
iniialei tatlui, evitnd astfel cheile duble.
Un arbore binar de cutare este un arbore ale crui noduri cuprind o singur
cheie de identicare, nodurile cu chei mai mici dect o valoare X a cheii asociate unui
anumit nod se gsesc n subarborele stng al acestui nod, iar nodurile ale cror chei
au valori mai mari dect X se gsesc n subarborele su drept.
Cutarea unei informaii identicate printr-o valoare X a cheii ncepe de la
rdcin i se termin n cel mai ru caz la unul din nodurile terminale, cutarea pre-
supunnd testarea a cel mult attea noduri cte nivele are arborele binar de cutare.
Dispunerea nodurilor arborelui pe nivele face ca numrul operaiilor de testare la
cutare s e mult mai mic dect n cazul listelor ordonate.
Metoda cutrii binare prezentate n capitolul anterior, poate explicat cu uur-
in cu ajutorul arborilor de cutare.
4
8
6 9
7 10 Nivelul 3
Nivelul 2
Nivelul 1
Nivelul 0
2
3 1
5
Figura 5.2: Exemplu de arbore binar de cutare
5.2. Arbori de cutare 183
5.2.1.2 Implementarea unui nod al arborelui ABC
Un nod al unui arbore ABC are urmtoarea structur:
Fiu_st Cheia Alte_info Fiu_dr
Figura 5.3: Structura nodului ABC
unde:
Fiu_st : reprezint adresa ului stnga;
Cheia: reprezint cmpul ales dup care este ordonat ABC i care veric relaia
(5.5);
Alte_info : alte informaii adiacente;
Fiu_dr : reprezint adresa ului dreapta;
Structura nodului, n implementarea Pascal este urmtoarea:
Type
Adresa = Nod
Nod = RECORD
Fiu_st : Adresa;
Cheia : tipcheia;
Alte_info : tipinfo;
Fiu_dr : Adresa;
end
5.2.1.3 Operaii ntr-un ABC
Operaiile n cazul arborilor binari de cutare sunt:
a. creare-iniializare;
b. inserare;
c. cutare;
d. tergere;
e. traversare:
Deoarece operaia de traversare a fost analizat i descris n capitolul anterior la
arbori binari (sectiunea 4.5.2), ne vom ocupa de celelalte operaii specice arborilor
binari de cutare.
184 5. Tehnici de cutare
a. Operaia de creare-inializare. Specicarea problemei de creare-iniializare,
avnd ca date de intrare ABC specicat prin adresa ROOT a nodului rdcin, este
urmtoarea:
DATE root;
REZULTATE root;
Descrierea algoritmului n Pseudocod este:
ALGORITMUL CREARE_INIIALIZARE ESTE: { Se creeaz un ABC vid }
ROOT := NIL;
SFALGORITM
b. Operaia de inserare. Specicarea problemei de inserare, avnd ca date de
intrare ABC cu adresa nodului rdcin ROOT i datele de inserat cheia_nou,
info_nou, este urmtoarea:
DATE ROOT, cheia_nou, info_nou;
REZULTATE ROOT;
Vom folosi subalgoritmul numit Creare_nod care va aloca dinamic spaiul de
memorie necesar noului nod de inserat i va completa cmpurile nodului ABC.
Observaie. Vom folosi n cele ce urmeaz o referin de tip Pascal pentru algoritmul
n Pseudocod, i anume:
adresa.cmp
unde adresa reprezint variabila de tip adres a nodului, iar cmp reprezint numele
cmpului nodului. Descrierea algoritmului n Pseudocod este:
SUBALGORITMUL Creare_nod (ch, inf) ESTE:
@Alocare_spaiu (NOU); { cererea de alocare spaiu pentru un nod }
NOU.u_st := NIL; {sistemul returneaz adresa noului nod n
variabila adres NOU}
NOU.u_dr := NIL;
NOU.cheia := ch;
NOU.info := inf;
SF-Creare_nod
ALGORITMUL INSERARE ESTE: { Se insereaz un nod nou ca nod terminal,
prima dat se caut nodul tat }
5.2. Arbori de cutare 185
CITETE cheia_nou, info_nou;
DAC ROOT = NIL ATUNCI { primul nod inserat }
CHEAM Creare_nod (cheia_nou, info_nou);
{ se aloc spaiu pentru noul nod de }
ROOT = NOU; {inserat la adresa NOU i se complet. cmpurile}
EXIT;
SFDAC
tmp := ROOT;
CTTIMP tmp <> NIL EXECUT
Tata := tmp;
DAC cheia_nou < tmp.cheia
ATUNCI tmp := tmp.u_st;
ALTFEL DAC cheia_nou > tmp.cheia
ATUNCI tmp := tmp.u_dr;
ALTFEL
TIPRETE (EROARE CHEIE DUBL);
EXIT;
SFDAC
SFDAC
SFCT
CHEAM Creare_nod (cheia_nou, info_nou);
DAC cheia_nou < tata.cheia
ATUNCI
tata.u_st := NOU;
ALTFEL
tata.u_dr := NOU;
SFDAC
SFALGORITM
c. Operaia de cutare. Specicarea problemei de cutare, avnd ca date de
intrare ABC cu adresa nodului rdcin ROOT i cheia nodului cutat cheia_caut,
este urmtoarea:
DATE root, cheia_caut;
REZULTATE adresa;
Observaie. adresa returnat de algoritmul de cutare este adresa nodului cu cheia
cheia_caut, dac acesta exist. Dac nodul cu cheia cheia_caut nu exist n ABC
atunci valoarea returnat va o adres nul.
186 5. Tehnici de cutare
ALGORITMUL CAUT ESTE:
CITETE cheia_caut;
tmp := ROOT;
CTTIMP (tmp <> NIL) EXECUT
DAC cheia_caut < tmp.cheia
ATUNCI tmp := tmp.u_st;
ALTFEL
DAC cheia_caut > tmp.cheia
ATUNCI tmp := tmp.u_dr;
ALTFEL @returneaz adresa tmp;
SFDAC
SFDAC
SFCT
@returneaz adresa NIL;
SFALGORITM
d. Operaia de tergere. Specicarea general a problemei de tergere este:
DATE root, cheia_de_sters;
REZULTATE root;
Exist mai multe situaii posibile, n funcie de numrul de i ai nodului de ters [Tre,
1984],:
Cazul 1. Nodul de ters este un nod terminal, deci fr i. Operaia de tergere
necesit eliminarea legturii nod_tat i nod_de_ters i eliberarea spaiului ocupat
de nodul de ters.
Exemplu: nodurile cu cheia 1, 4, 7, 10 din ABC gura 5.2.
Cazul 2. Nodul de ters are un singur u. Operaia de tergere necesit realizarea
legturii nod_tat i nod_u (stnga sau dreapta) al nodului de ters i eliberarea
spaiului ocupat de nodul de ters.
Exemplu: nodurile cu cheia 3, 6, 9 din ABC gura 5.2.
Cazul 3. Nodul de ters are doi i. n aceast situaie, nodul de ters trebuie nlocuit
i abia dup aceea poate eliminat. Nodul nlocuitor poate nodul cu cheia cea mai
mare din punct de vedere lexicograc din subarborele stng al nodului de ters sau
nodul cu cheia cea mai mic din subarborele drept al nodului de ters.
Exemplu: nodurile cu cheia 2, 5, 8 din ABC gura 5.2. Nodul nlocuitor al nodului
cu cheia 2 este nodul cu cheia 1 din subarborele stng sau nodul cu cheia 3 din
5.2. Arbori de cutare 187
subarborele su drept. Nodul nlocuitor al nodului cu cheia 5 este nodul cu cheia 4
din subarborele stng sau nodul cu cheia 6 din subarborele su drept. Nodul nlocuitor
al nodului cu cheia 8 este nodul cu cheia 7 din subarborele stng sau nodul cu cheia
9 din subarborele su drept.
Observaie. Pentru a gsi nodul nlocuitor al unui nod de ters n Cazul 3, acesta
poate gsit astfel: dac nodul nlocuitor este nodul cu cheia cea mai mare din punct
de vedere lexicograc din subarborele stng al nodului de ters atunci se navigheaz
de la nodul de ters un pas la stnga i orici pai la dreapta, pn ajungem la o
legtur nul. Dac nodul nlocuitor este nodul cu cheia cea mai mic din punct de
vedere lexicograc din subarborele drept al nodului de ters atunci se navigheaz de la
nodul de ters un pas la dreapta i orici pai la stnga, pn ajungem la o legtur
nul.
Descrierea general a algoritmului de tergere, n Pseudocod este:
ALGORITMUL TERGERE ESTE:
CITETE cheia_de_sters;
DAC ROOT = NIL ATUNCI
TIPRETE (EROARE ARBORE VID);
EXIT;
SFDAC
tmp := ROOT; { Se caut nodul de ters }
CTTIMP (tmp <> NIL) I (cheia_de_sters <> tmp.cheia) EXECUT
Tata := tmp;
DAC cheia_nou < tmp.cheia
ATUNCI tmp := tmp.u_st;
ALTFEL tmp := tmp.u_dr;
SFDAC
SFCT
DACA tmp = NIL ATUNCI
TIPRETE (EROARE NODUL NU EXIST N ABC);
EXIT;
SFDAC
DAC tmp.u_st = NIL i tmp.u_dr = NIL ATUNCI
CHEAM Cazul_1 (ROOT, tata, tmp); { Cazul 1 }
EXIT;
SFDAC
DAC tmp.u_st = NIL XOR tmp.u_dr = NIL ATUNCI
188 5. Tehnici de cutare
CHEAM Cazul_2 (ROOT, tata, tmp); { Cazul 2 }
EXIT;
SFDAC
CHEAM Cazul_3 (ROOT, tata, tmp); { Cazul 3 }
SFALGORITM
SUBALGORITMUL Cazul_1 (rad, t, adr) ESTE:
DAC t.u_st = adr ATUNCI
t.u_st := NIL;
ALTFEL
t.u_dr := NIL;
@Eliberare spaiu (adr); { Eliberarea spaiului de la adresa adr }
SF-Cazul_1
SUBALGORITMUL Cazul_2 (rad, t, adr) ESTE:
DAC t.u_st = adr ATUNCI { Nodul de ters este ul stnga al nodului tata}
DAC adr.u_st = NIL ATUNCI
t.u_st := adr.u_dr;
ALTFEL
t.u_st := adr.u_st;
ALTFEL { Nodul de ters este ul dreapta al nodului tata}
DAC adr.u_dr = NIL ATUNCI
t.u_dr := adr.u_st;
ALTFEL
t.u_dr := adr.u_dr;
@Eliberare spaiu (adr); { Eliberarea spaiului de la adresa adr }
SF-Cazul_2
SUBALGORITMUL Cazul_3 (rad, t, adr) ESTE:
tmp := adr.u_st; { Se caut nodul nlocuitor un pas la stnga}
tata := tmp;
CTTIMP tmp.u_dr <> NIL EXECUT { Orici pai la dreapta}
tata := tmp;
tmp := tmp.u_dr; {Adresa tatlui nodului nlocuitor este
n variabila tata}
SFCT { Adresa nodului nlocuitor este n variabila tmp}
adr.cheia := tmp.cheia; { nlocuim nodul de ters cu nodul nlocuitor}
adr.info := tmp.info; { nlocuim nodul de ters cu nodul nlocuitor}
5.2. Arbori de cutare 189
tata.u_dr := tmp.u_st; { Eliminm legtura tata - nodul nlocuitor}
@Eliberare spaiu (tmp); { Eliberarea spaiului nod nlocuitor de la adresa tmp }
SF-Cazul_3
5.2.1.4 Probleme rezolvate
Exemplul 5.2.1. Problema arborilor asociai expresiilor aritmetice. Fiind date n ex-
presii aritmetice, sintactic corecte, care cuprind paranteze, operanzi notai cu literele
mici din alfabet i operatori binari sau unari din mulimea +, , , /, s se con-
struiasc i s se aeze n postordine arborele binar asociat ecrei expresii [Dal,
1988].
Arborele binar asociat expresiei aritmetice (a+b) c d este prezentat n gura
urmtoare:
- binar
$ unar
b
a
c
d $
*
+
-
Se observ c rdcina cuprinde simbolul ultimei operaii, subarborele stng, iar
nodul din dreapta corespunde operandului drept; aceeai regul se aplic subarborilor.
Operatorul "-" unar din expresie s-a transformat n arborele binar n "&" pentru a-l
distinge de cel binar; nodul asociat operatorului are numai subarbore drept ( operaia
este unar ).
190 5. Tehnici de cutare
Program arbori_asociati_expresiilor_aritmetice ;
type
reper =nod ;
nod = record
v : char ;
stg, dr : reper ;
end ;
var
rad : reper ;
x : pointer ;
i, n : byte ;
car : char ;
procedure citire ;
begin
if not eoln then read(car)
end ;
procedure postordine ( p : reper );
begin
if p < > NIL then
begin
postordine (p .stg) ;
postordine (p .dr) ;
write(p .v);
end ;
end ;
procedure expresie (var p : reper ) ; forward ;
procedure termen (var p : reper ) ; forward ;
procedure factor (var p : reper ) ;
{ creeaza nodul terminal p sau subarborele de radacina p }
{ asociat unei expresii aritmetice cuprinsa ntre () }
begin
if car = ( then
begin
citire ;
expresie (p) ; { aici car =) }
end ; else
begin
5.2. Arbori de cutare 191
new(p) ;
p .v := car ;
p .stg := NIL ;
p .dr := NIL ;
end ;
citire ;
end ;
procedure termen ;
var q : reper ;
begin
factor ( p ) ;
while car in [ *, / ] do
begin
new ( q ) ;
q .v := car ;
q .stg := p ;
citire ; { operandul 2 ncepe dup car }
factor (q . dr) ; { creeaz si leag n dr. nodului q }
p := q ; { subarb. asociat operandului 2 al lui car }
end ;
end ;
procedure expresie ;
var q : reper ;
begin
if car in [ +, - ] then { expresia ncepe cu + sau - }
if car = - then
begin{ car = - unar }
new ( p ) ;
p .v := $ ; { $= - unar }
p .stg := NIL ;
citire ;
termen(p .dr) ;
end
else
begin{ car =+ unar }
citire ;
192 5. Tehnici de cutare
termen ( p );
end
else termen ( p ) ;
while car in [ +, - ] do
begin
new ( q ) ;
q .v := car ;
q .stg := p ;
citire ;
termen ( q .dr) ;
p := q;
end end ;
BEGIN { programul principal }
mark (x) ; {retine vrful zonei HEAP }
write ( n=) ; readln (n);
for i:= 1 to n do
begin
read ( car ) ;
expresie ( rad ) ;
postordine (rad );
writeln ;
readln ;
release (x) ; { elibereaz memoria ocupata dinamic}
end ;
END.
Pentru n = 2 vom obine rezultatul:
(a +b)

(c d)
abc +cd

a +b
a$b+
5.2.2 Arbore binar de cutare balansat n nlime
5.2.2.1 Descrierea general a arborelui balansat n nlime
Primul tip de arbore balansat este Arborele Binar de Cutare Balansat n
nlime - ABCBI . ntr-un astfel de arbore ncercm meninerea tuturor nodurilor
5.2. Arbori de cutare 193
frunz la aceeai distant fa de rdcin.
n Figura 5.4 a) este prezentat un arbore binar de cutare balansat n
nlime, iar n Figura 5.4 b) este prezentat un arbore binar debalansat [Tre, 1984].
B
B
B
B
L B
a) b)
Figura 5.4:
Pentru a prevenii debalansarea arborelui, asociem un indicator de balansare
pentru toate nodurile arborelui. Indicatorul de balansare poate s conin trei valori
notate astfel:
nod greu stnga (L)
nod greu dreapta (R)
nod balansat (B)
Deniia 5.2.1. Nod greu stnga (L): Un nod al unui ABCBI se numete nod
greu stnga, dac nlimea subarborelui su stng este mai mare cu 1 dect nlimea
subarborelui su drept.
Deniia 5.2.2. Nod greu dreapta (R): Un nod al unui ABCBI se numete
nod greu dreapta, dac nlimea subarborelui su drept este mai mare cu 1 dect
nlimea subarborelui su stng.
Deniia 5.2.3. Nod balansat (B): Un nod al unui ABCBI se numete nod
balansat, dac nlimea subarborelui su stng este egal cu nlimea subarborelui
su drept.
194 5. Tehnici de cutare
Deniia 5.2.4. Nod critic (C): Un nod al unui ABCBI se numete nod critic,
dac nu este nod greu dreapta, nod greu stnga sau nod balansat.
ntr-un ABCBI ecare nod trebuie se ae in una din aceste trei stri, adic s
e nod greu dreapta, nod greu stnga sau nod balansat.
Deniia 5.2.5. Un arbore binar de cutare se numete arbore binar de cutare
balansat n nlime ABCBI, dac are doar noduri greu stnga, noduri greu dreapta
sau noduri balansate.
Dac exist un nod care nu satisface nici una din aceste trei stri, atunci arborele
se numete arbore binar debalansat.
Deniia 5.2.6. Un ABCBI se numete arbore binar de cutare debalansat n
nlime dac conine cel puin un nod critic.
5.2.2.2 Implementarea unui nod al arborelui ABCBI
Un nod al unui arbore ABCBI are urmtoarea structur:
Fiu_st Cheia Alte_info IB Fiu_dr
Figura 5.5: Structura nodului ABCBI
unde:
Fiu_st : reprezint adresa ului stnga;
Cheia: reprezint cmpul ales dup care este ordonat ABCBI ;
Alte_info : alte informaii;
IB : indicatorul de balansare;
Fiu_dr : reprezint adresa ului dreapta;
Structura nodului, n implementarea Pascal, este urmtoarea:
Type
Adresa = Nod
Nod = RECORD
Fiu_st : Adresa;
Cheia : tipcheia;
Alte_info : tipinfo;
IB : char;
Fiu_dr : Adresa;
end
5.2. Arbori de cutare 195
5.2.2.3 Operaii ntr-un ABCBI
Operaiile n cazul arborilor binari de cutare balansai n nlime sunt aceleai ca
i la arborii binari de cutare, i anume:
a. creare-iniializare;
b. inserare-balansare;
c. cutare;
d. tergere;
e. traversare.
Operaiile creare-iniializare, cutare i traversare sunt identice cu operaiile de
la arborii binari de cutare. Doar operaiile de inserare-balansare i tergere sunt
specice i vor detaliate n cele ce urmeaz.
a. Operaia de inserare. n cazul operaiei de inserare al unui nod, presupunem
c inserarea se face la nivelul unui nod terminal, dup regula general de inserare de la
arborii binari de cutare. Numai la acele noduri se schimb indicatorul de balansare
n cazul unui astfel de inserri, care se a pe un drum cuprins ntre rdcin arborelui
i noul nod terminal inserat, numit drum de inserare. Posibilele schimbri pentru
un nod, aat pe drumul de inserare sunt urmtoarele [Tre, 1984]:
Cazul 1. Nodul era nod greu dreapta sau nod greu stnga i a devenit balansat.
Cazul 2. Nodul era balansat i a devenit nod greu dreapta sau nod greu stnga.
Cazul 3. Nodul era un nod greu, iar noul nod este nserat n subarborele su
greu, crend un subarbore debalansat. Un astfel de nod se numete nod critic.
n Cazul 1, n urma operaiei de inserare, indicatorul de balansare (IB) a nodurilor
strmo ale nodului de inserat, aate pe drumul de inserare, rmn neschimbate, cu
excepia noului tat. Acest exemplu este prezentat n Figura 5.6 Cazul 1. n acest
exemplu nodul inserat este nodul cu cheia 3.
n Cazul 2, dup cum se vede i n Figura 5.6 Cazul 2., indicatorii de balansare
(IB) a nodurilor strmo, situate pe drumul de inserare se pot modica. n acest
exemplu nodul de inserat este nodul cu cheia 4.
n Cazul 3, n urma unei operaii de inserare, arborele devine debalansat i se
creeaz noduri critice. n Figura 5.6 Cazul 3. este prezentat un astfel de exemplu,
aprut n urma inserrii nodului cu cheia 4: nodul cu cheia 5 se transform n nod
critic iar arborele binar devine debalansat.
Operaia de inserare poate duce la crearea unor noduri critice, deci la debalansarea
arborelui. Pentru a putea pstra caracteristica de ABCBI, este necesar efectuarea
unei operaii specice, numit rebalansare a arborelui, care s duc la eliminarea
nodurilor critice i la transformarea lor n noduri greu dreapta, greu stnga sau ba-
196 5. Tehnici de cutare
lansat.
Sunt dou cazuri de rebalansare, care se divid ecare n dou subcazuri, corespun-
ztoare direciei grele stnga sau dreapta care a dus la apariia nodului critic [Tre,
1984].
B
B
B
B B
R
4
B
B
B
L
3
R
8
6 1
7
2
5
B B B
B
L
B
B 3 8
6 1
7
B
2
5
Cazul 2
Cazul 1
R
B
R
B
L Critic
4
3
1
6 2
5
B
Cazul 3
Figura 5.6:
Cazul 1. Rebalansare prin rotaie simpl. Acest caz apare cnd operaia de
inserare s-a fcut pe direcia grea a nodului care a devenit critic. Cele dou sub cazuri
sunt:
Cazul 1.a. Rebalansare prin rotaie simpl la dreapta. Acest caz apare cnd
operaia de inserare s-a fcut pe direcia grea stng a nodului care a devenit critic.
Cazul 1.b. Rebalansare prin rotaie simpl la stnga. Acest caz apare cnd
operaia de inserare s-a fcut pe direcia grea dreapta a nodului care a devenit critic.
O reprezentare a cazului 1.a, este n Figura 5.7, unde T1, T2 i T3 reprezint
5.2. Arbori de cutare 197
subarbori, iar NOU reprezint noul nod de inserat. Expresia din partea de jos a
dreptunghiurilor reprezint nlimea subarborilor, nainte i dup inserare.
De exemplu, n Figura 5.7 (a.1) presupunem c n urma unei operaii de inserare
nodul X, din nod greu stnga, a devenit critic. Atunci arborele binar devine
debalansat. Problema se rezolv dac rotim la dreapta arborele n jurul nodului
nodul Y, Figura 5.7 (a.2).
T3
n
T2
n
NOU
T1
n+1
Y
X
NOU
T1
n+1
T3
n
T2
n
X
Y
a.2 a.1
Figura 5.7: Exemplu de soluionare a debalansrii ABCBI, prin rotaie simpl la
dreapta n jurul nodului Y
De exemplu, n Figura 5.8 (b.2) presupunem c n urma unei operaii de inserare
nodul X, din nod greu dreapta, a devenit critic. Atunci arborele binar devine
debalansat. Problema se rezolv dac rotim la stnga arborele n jurul nodului
nodul Y, Figura 5.8 (b.1).
Cazul 2. Rebalansare prin rotaie dubl. Acest caz apare cnd operaia de
inserare s-a fcut pe direcia opus direciei grele a nodului care a devenit critic. Cele
dou subcazuri sunt:
Cazul 2.a. Rebalansare prin rotaie dubl la dreapta. Acest caz apare cnd
operaia de inserare s-a fcut pe direcia opus direciei grele stng a nodului care a
devenit critic.
Cazul 2.b. Rebalansare prin rotaie dubl la stnga. Acest caz apare cnd
operaia de inserare s-a fcut pe direcia opus direciei grele dreapta a nodului care
a devenit critic.
198 5. Tehnici de cutare
NOU
T3
n+1
T2
n
T1
n
X
Y
T1
n
T3
n+1
T2
n
Y
X
NOU
b.2
b.1
Figura 5.8: Exemplu de soluionare a debalansrii ABCBI, prin rotaie simpl la
stnga n jurul nodului Y
X
Y
T4
n+1
NOU
Y
T1
n+1
NOU
T2
n+1
T3
n
T2
n+1
Z
T4
n+1
T3
n
X
Z
a.1
T1
n
a.2
Figura 5.9: Exemplu de soluionare a debalansrii ABCBI, prin rotaie dubl la
stnga n jurul nodului Z
5.2. Arbori de cutare 199
X
Y
T4
n+1
T1
n+1
NOU
X
T1
n+1
NOU
T2
n+1
T3
n
T2
n+1
Z
T4
n+1
T3
n
Y
Z
b.1 b.2
Figura 5.10: Exemplu de soluionare a debalansrii ABCBI, prin rotaie dubl la
dreapta n jurul nodului Z
Cazul doi, care este reprezentat n Figura 5.9 i Figura 5.10, este asemntor
cu primul caz, cu excepia c nodul Y devine nod greu n direcia opus n care nodul
X era nod greu. Este clar c nodul Z trebuie balansat prioritar fa de inserare.
Specicarea problemei de inserare, avnd ca date de intrare ROOT, cheia_nou,
info_nou, este urmtoarea:
DATE root, cheia_nou, info_nou;
REZULTATE root;
Descrierea algoritmului n Pseudocod este:
ALGORITMUL INSERARE ESTE: { Se insereaz un nod nou i dac este cazul se
rebalanseaz arborele }
CITETE cheia_nou, info_nou;
DAC @este primul nod inserat ATUNCI
CHEAM Creare_nod (cheia_nou, info_nou);
EXIT;
SFDAC
DAC @nu este cheie dubl ATUNCI
@ataeaz noul nod n arbore;
ALTFEL
TIPRETE Eroare - Cheie dubla;
200 5. Tehnici de cutare
EXIT;
SFDAC
@calculeaz IB (indicatorii de balansare);
@caut un nod debalansat;
DAC @nu exist nod critic ATUNCI
EXIT;
SFDAC
DAC @nodul era balansat i a devenit greu sau nodul era greu i a devenit balansat
ATUNCI @calculeaz IB (indicatorii de balansare);
EXIT;
SFDAC
@rebalanseaz arborele;
SFALGORITM
b. Operaia de tergere. Specicarea general a problemei de tergere este:
DATE root, cheia_de_sters;
REZULTATE root;
Descrierea general a algoritmului de tergere, n Pseudocod este:
@Caut nodul marcat pentru tergere cu cheia cheia_de_sters
DAC @nodul cu cheia cheia_de_sters are doi i
ATUNCI @caut succesorul (inordine) nodului cu cheia cheia_de_sters;
@terge succesorul (inordine ) nodului cu cheia cheia_de_sters;
@schimb nodul marcat pentru tergere cu succesorul (inordine);
ALTFEL @terge nodul marcat i schimb cu ul (dac exist )
SFDAC
@Rebalanseaz arborele pe drumul de cutare;.
5.2.2.4 Probleme rezolvate
Exemplul 5.2.2. Implementarea PASCAL a operaiilor efectuate ntr-un ABCBI :
creare-iniializare, inserare, cutare, tergere, traversare.
Program operaii ABCBI;
type
adresa = nod ;
nod = record
lptr , rptr : adresa; {lptr, rptr: pointeri ctre subarborele stng respectiv drept}
key : integer ;
5.2. Arbori de cutare 201
end ;
var
root , tata , nou , temp , nodp : adresa ;
c , bi1 : char ;
s : integer ;
Procedure creare ( var cap : adresa ) ;
begin
cap := nil ;
end ;
Procedure inserare ( var cap : adresa ; cheia : integer );
var curent : adresa ; { procedura care insereaz un nod nou }
begin
curent := cap ;
tata := cap ;
while curent <> nil do
if curent.key < cheia then begin
tata := curent ;
curent := curent.rptr ;
end
else
if curent.key > cheia then begin
tata := curent ;
curent := curent.lptr ;
end
else begin
writeln ( Cheie dubl ! ) ;
readln ;
exit ;
end ;
new ( nou ) ;
nou.key := cheia ;
nou.lptr := nil ;
nou.rptr := nil ;
if cap = nil then begin
cap := nou ;
exit ;
202 5. Tehnici de cutare
end;
if cheia < tata.key then tata.lptr := nou
else tata.rptr := nou ;
balansinalt ;
end;
Procedure caut (root : adresa ; ch : integer ) ;
Begin
{ procedura care caut un anumit nod }
temp := root ; tata := root ;
while (ch <> temp.key ) and ( temp <> nil ) do
begin
tata := temp ;
if temp.key < ch then temp := temp.rptr
else temp := temp.lptr ;
end ;
end ;
Procedure sterg ; { procedura de tergere a unui nod }
var u , predec , tatap : adresa ;
begin
if ( temp.lptr = nil ) and ( temp.rptr = nil ) then {nodul de ters nu
are nici un u}
if temp.key < tata.key then
begin
tata.lptr := nil ;
dispose ( temp ) ;
end
else begin
tata.rptr := nil ;
dispose ( temp ) ;
end
else if ( temp.lptr = nil ) xor ( temp.rptr = nil ) then
{ nodul de ters are un singur u }
begin
if temp.lptr = nil then u := temp.rptr
else u := temp.lptr ;
if temp.key < tata.key then tata.lptr := u
else tata.rptr := u ;
5.2. Arbori de cutare 203
dispose ( temp ) ;
end
else begin
predec := temp.lptr ; tatap := predec ;
while predec.rptr <> nil do
begin
tatap := predec ; predec := predec.rptr ;
end ;
temp.key := predec.key ;
if predec.lptr <> nil then begin
tatap.rptr := predec.lptr ;
dispose ( predec ) ;
end ;
if predec = tatap then begin
temp.lptr := nil ;
dispose ( predec ) ;
end ;
end ;
end ;
Procedure terge ( rdcina : adresa ; cheias : integer ) ;
begin
cauta ( rdcina , cheias ) ;
if temp <> nil then begin
write ( Sterg elementul cu cheia , cheias , ... ) ;
sterg ;
writeln ( OK! ) ;
end
else begin
writeln ( Cheie inexistenta ! ) ; exit ;
end ;
end ;
Procedure inordine ( def : adresa ) ; { traversare inordine }
begin
if def <> nil then
begin
inordine ( def.lptr ) ;
204 5. Tehnici de cutare
write ( def.key : 3 ) ;
inordine ( def.rptr ) ;
end ;
end ;
Procedure preordine ( def : adresa ) ; { traversare preordine }
begin
if def <> nil then
begin
write ( def.key : 3 ) ;
preordine ( def.lptr ) ;
preordine ( def.rptr ) ;
end ;
end ;
Procedure postordine ( def : adresa ) ; { traversare postordine }
begin
if def <> nil then
begin
postordine ( def.lptr ) ;
postordine(def.rptr);
write ( def.key : 3 ) ;
end ;
end ;
Procedure meniu ;
begin
repeat
clrscr ;
writeln ( Optiuni : C-Creare ) ;
writeln ( I-Inserare ) ;
writeln ( S-tergere ) ;
writeln ( T-Traversare-N-Inordine ) ;
writeln ( T-Traversare-P-Preordine ) ;
writeln ( T-Traversare-O-Postordine ) ;
writeln ( ESC-Ieire ) ;
c := readkey ;
case upcase ( c ) of
5.2. Arbori de cutare 205
C : begin
writeln ; writeln ( * CREARE * : 15 ) ; writeln ;
write ( Creez rdcina... ) ;
creare ( root ) ; writeln ( OK! ) ;
readkey ;
end ;
I : begin
writeln ; writeln( * INSERARE * : 15 ) ; writeln ; writeln ;
write ( Cheia : ) ; readln( s ) ; writeln ;
insere ( root , s ) ;
end ;
S : begin
writeln ; writeln ( *TERGERE * : 15 ) ; writeln ;
write ( Cheia elementului pt. sters: ) ;
readln ( s ) ; sterge ( root , s ) ;
end ;
T : begin
writeln ; writeln ( * TRAVERSARE * : 15 ) ; writeln ;
write ( Optiunea: ) ; readln(c) ;
if root.key = 0 then
begin
writeln ; writeln ( Arbore vid ! : 15 ) ;
c := ;
end ; writeln ;
case upcase ( c ) of
N : begin
write ( Inordine: ) ;
inordine ( root ) ;
readkey ;
end ;
P : begin
write ( Preordine: ) ;
preordine ( root ) ;
readkey ;
end ;
O : begin
write ( Postordine: ) ;
postordine ( root ) ;
206 5. Tehnici de cutare
readkey ;
end ;
else writeln ( Ai apsat o tast gresit ! ) ;
end ;
end ;
end ;
until c = # 27 ;
end ;
BEGIN
meniu ;
END.
5.2.2.5 Performanele algoritmilor n ABCBI
Performana algoritmului ce corespunde operaiei de inserare n arborele binar bal-
ansat n nlime cu n noduri este de ordinul O(1.5 log
2
(n + 1)) [Knu, 1976].
Performana algoritmului ce corespunde operaiei de cutare este identic cu per-
formana algoritmului de cutare a arborilor binari de cutare, adic este de ordinul
O(log
2
n).
n referina [Tre, 1984], se arat c performana algoritmului ce corespunde opera-
iei de tergere este de ordinul O(log
2
n).
5.2.3 Arbore binar de cutare balansat n greutate ABCBG
5.2.3.1 Descrierea general a arborelui balansat n greutate
Am vzut n (5.4) faptul c organizarea datelor inueneaz semnicativ perfor-
manele algoritmilor de cutare. Concluzia modului de organizare a datelor conform
cu (5.4) este evident: dac datele nu sunt echiprobabil cutate, atunci datele cele mai
cutate, sau cu probabilitatea de cutare cea mai mare, trebuie s se gseasc la n-
ceputul drumului de cutare. La un arbore binar de cutare procesul de cutare ncepe
ntotdeauna de la nodul rdcin. Avem atunci stabilit urmtorul el: dac datele
organizate sub forma unei structuri de tip arbore binar de cutare sunt echiproba-
bile, au aceeai probabilitate de cutare, atunci arborii binari de cutare balansai
n nlime sunt structura cea mai potrivit. Dac ns datele organizate sub forma
unui arbore binar de cutare nu sunt echiprobabile, avem nevoie de o alt structur
arborescent binar de cutare, care s dispun n arbore datele cele mai cutate ct
mai aproape de nceputul drumului de cutare adic de rdcin.
5.2. Arbori de cutare 207
Introducem astfel o nou structur de date arborescent, i anume, arborele
binar de cutare balansat n greutate ABCBG, a crei regul de organizare
poate formulat astfel: cele mai des cutate noduri se a ct mai aproape de
rdcin .
Dac probabilitatea de cutare a unei date particulare este necunoscut, putem s
folosim formula (5.2), ca un raport dintre numrul de accesri a unei asemenea date i
numrul total de accesri al structurii de date arborescente. Aceast probabilitate de
cutare poate meninut dinamic, dac avem grij s incrementm la ecare acces
al unei date, variabila corespunztoare numrului de accesri al acelei date precum i
numrul total de accesri a structurii de date arborescente.
Rezult resc c ecare nod al unui astfel de ABCBG are nevoie de un cmp
suplimentar de informaie, i anume, numrul de cte ori a fost accesat acea infor-
maie i pe care o vom numi greutatea nodului respectiv.
Observaie. n orice arbore (subarbore) nodul rdcin este cel mai greu nod.
Arborele prezentat n gura de mai jos, este o structur de date de tip ABCBG.
Se observ c n primul rnd avem un ABC deoarece, lexicograc, avem respectat
regula de organizare a arborilor binari de cutare. De asemenea, se observ c nodurile
cele mai grele se gsesc la nceputul drumului de cutare, adic ct mai aproape de
nodul rdcin [Tre, 1984].
T
1
Lalea 5 Tei 3
Garoaf 4 Molid 2 Zorele 1
4 Dalie
6 Pin
Figura 5.11: Exemplu de arbore binar de cutare T
1
balansat n greutate ABCBG
208 5. Tehnici de cutare
Regula de plasare al unui nod n arborele binar de cutare balansat n greutate
poate exprimat n mod recursiv, dup urmtoarea regul [Aho, 1987]:
1. Nodul rdcin al oricrui arbore (subarbore) este nodul cu cea mai mare greu-
tate din mulimea de noduri care constituie arborele (subarborele);
2. Subarborele stng al oricrui arbore (subarborelui) este compus din noduri a
cror valoare lexical este mai mic dect nodul rdcin;
3. Subarborele drept al oricrui arbore (subarborelui este compus din noduri a
cror valoare lexical este mai mare dect nodul rdcin.
n cazul arborelui binar de cutare balansat n greutate, la ecare operaie de
inserare sau la o orice operaie de accesare a unui anumit nod, greutatea nodului este
incrementat cu 1. Dac se insereaz un nod nou n arbore, acesta va poziionat
conform cu regulile generale de inserare de la arborii binari de cutare, ca i nod
terminal, greutatea nodului ind iniializat cu 1.
S considerm n continuare acelai arbore binar de cutare, dar care s nu mai
e balansat n greutate.
T
2
Lalea 5 Zorele 1 6 Pin 4 Dalie
Molid
4 Garoaf 3 Tei
2
Figura 5.12: Exemplu de arbore binar T
2
de cutare debalansat n greutate
S comparm performanele algoritmilor de cutare n cei doi arbori de cutare
T
1
(balansat n greutate) i T
2
(debalansat n greutate):
ALOS
T
1
=
6
25
1 +
5
25
2 +
3
25
2 +
4
25
3 +
2
25
3 +
1
25
3 +
4
25
4 = 2.36
ALOS
T
2
=
2
25
1 +
4
25
2 +
3
25
2 +
4
25
3 +
5
25
3 +
6
25
3 +
1
25
3 = 2.56
5.2. Arbori de cutare 209
Se observ clar c arborele binar de cutare balansat n greutate are performane
de cutare mai bune dect un arbore binar de cutare. Cu ct structura de date
arborescent este mai mare ca dimensiuni, diferenele de performan se accentueaz
n favoarea ABCBG.
5.2.3.2 Implementarea unui nod al arborelui ABCBG
Un nod al unui ABCBG are urmtoarea structur:
Fiu_st Cheia Alte_info Greutate Fiu_dr
Figura 5.13: Structura nodului ABCBG
unde:
Fiu_st : reprezint adresa ului stnga;
Cheia: reprezint cmpul ales dup care este ordonat ABCBG;
Alte_info: alte informaii;
Greutate: greutatea nodului, reprezentat prin numrul de accesri ale nodului;
Fiu_dr: reprezint adresa ului dreapta;
Structura nodului n implementarea Pascal este urmtoarea :
Type
Adresa = Nod
Nod = RECORD
Fiu_st : Adresa;
Cheia : tipcheia;
Alte_info : tipinfo;
Greutate : byte;
Fiu_dr : Adresa;
end
5.2.3.3 Operaii ntr-un ABCBG
Operaiile n cazul arborilor binari de cutare balansai n greutate sunt aceleai ca
i la arborii binari de cutare, i anume:
a. creare-iniializare;
b. inserare-balansare;
c. cutare;
d. tergere;
e. traversarea:
210 5. Tehnici de cutare
Operaiile creare-iniializare, inserare i traversare sunt identice cu operaiile de la
arborii binari de cutare. Doar operaiile de cutare i tergere sunt specice i vor
detaliate n cele ce urmeaz. Operaia de cutare poate modica greutatea unui nod
i debalansa arborele.
c. Operaia de cutare
Balansarea unui ABCBG este ilustrat n Figura 5.14 [Tre, 1984]:
Subarbore stng
COPIL
PARINTE
Subarbore drept
COPIL
Subarbore drept
PARINTE
COPIL
BUNIC
a)
Subarbore stng
COPIL
Subarbore drept
COPIL
Subarbore drept
PARINTE
COPIL
PARINTE
BUNIC
b)
Figura 5.14: Operaia de balansare a unui ABCBG
5.2. Arbori de cutare 211
n gura 5.14 a), presupunem c n urma unei accesri a nodului COPIL, greu-
tatea acestuia devine mai mare dect greutatea nodului PARINTE, deci arborele
devine debalansat n greutate. n gura 5.14 b), se prezint strategia de balansare.
Observaie. Vom presupunem existenta unei stive care este folosit pentru a memora
drumul de cutare, de la nodul rdcin pn la nodul cutat. Aceast stiv va
necesar pentru operaia de tergere.
Specicarea problemei de inserare, avnd ca date de intrare cheia_caut,
info_nou, este urmtoarea:
DATE root, cheia_caut, info_nou;
REZULTATE root;
Descrierea algoritmului n Pseudocod este:
ALGORITMUL INSERARE ESTE: { Se insereaz un nod nou i dac este cazul se
rebalanseaz arborele }
CITETE cheia_caut, info_nou;
@Caut nodul cu cheia cheia_caut i memoreaz drumul de cutare n stiv;
DAC @nodul cutat este gsit
ATUNCI @incrementeaz greutatea cu 1;
@balanseaz arborele (dac este nevoie );
ALTFEL TIPRETE cutare fr succes ;
SFDAC
SFALGORITM
Implementarea algoritmului de cutare n Pascal este:
Function cutare (rad : adresa ; cheia_caut : char ) : adresa;
begin temp := rad ;
tata := rad ;
reset (st , ind ) ; { reset (st,ind) iniializeaz stiva }
while ( temp <> nil ) and ( temp.key <> cheia_caut) do
begin
if cheia_caut < temp.key then
begin
tata := temp;
push (st , ind , tata ); {procedura push introduce n stiva }
212 5. Tehnici de cutare
temp := temp.lptr ; {strmoii nodului cutat }
end
else
begin
tata := temp ;
push ( st , ind , tata ) ;
temp := temp.rptr ;
end ;
end ;
if temp.key = cheia_caut then
begin
inc ( temp.weight ) ;
writeln ( Cutare cu succes Informaia exist ) ;
cautare := temp ;
rebalansare ( temp, tata ) ; { rebalanseaz arborele dac este necesar }
exit ;
end
else
begin
cautare := nil ;
writeln ( Cutare cu insucces Informaia nu exist ) ;
end ;
end ;
d. Operaia de tergere
n cazul operaiei de tergere al unui nod, avem 4 cazuri care trebuie examinate [Tre,
1984].
Cazul 1. Nodul de ters este un nod frunz. In acest caz, tergerea este simpl,
tergem legtura care leag nodul frunz de nodul printe.
Cazul 2. Nodul este un nod neterminal, care nu are subarbore drept, i nodul de
ters este un nod u stnga. n acest caz ul stng al nodului printe va deveni egal cu
ul stng al nodului marcat pentru tergere. Aceeai rezolvare pentru cazul simetric.
Cazul 3. Nodul este un nod neterminal, care nu are subarbore stng, i nodul de
ters este un nod u stnga. n acest caz ul stng al nodului printe va deveni egal cu
ul drept al nodului marcat pentru tergere. Aceeai rezolvare pentru cazul simetric.
Cazul 4. Nodul este nod neterminal, cu ambii subarbori nenuli. In acest caz tergerea
direct a nodului ar duce la debalansarea arborelui. Pentru a nu debalansa arborele,
5.2. Arbori de cutare 213
se va nlocui nodul de ters cu un nod urma, i anume cu acela care are cea mai
mare greutate. n urma aplicrii acestei nlocuiri, ne vom regsi ntr-una din regulile
exprimate prin Cazurile 1,2,3 sau 4. Repetm regula 1,2, 3 sau 4, pn cnd se poate
terge nodul dorit
Specicarea general a problemei de tergere este:
DATE root, cheia_de_sters;
REZULTATE root;
Descrierea general a algoritmului recursiv de tergere, n Pseudocod este:
SUBALGORITMUL sterge (radacina, cheia_s) ESTE:
DAC @nodul de sters cu cheia_s este nod terminal sau are un subarbore vid
ATUNCI @terge nodul; { Cazurile 1, 2, 3 }
ALTFEL @interschimb nodul de ters cu nodul urma cel mai greu;
{ Cazul 4 }
SFDAC
CHEAM sterge (radacina, cheia_s);
SF-sterge
5.2.3.4 Probleme rezolvate
Exemplul 5.2.3. Implementarea PASCAL a operaiilor efectuate ntr-un ABCBG:
creare-iniializare, inserare, cutare, tergere, traversare.
program ABCBG;
const max=100;
type adresa = nod;
nod = record
lptr : adresa ; key : char ;
info : string[30] ;
rptr : adresa ;
weight : word ;
end ;
str = string[30] ;
stiva = array[0..max] of adresa ;
top = 0..max ;
var
tata , temp , copil , root , rad : adresa ;
ch : char ;
student : nod ;
214 5. Tehnici de cutare
i , n : integer ;
st : stiva ;
ind : top ;
Procedure reset (st:stiva ; var indic:top ) ; {iniializeaz stiva }
begin
indic := 0 ;
end ;
Function fullstack(indic:top) : boolean ; { stiv plin ?}
begin
if indic = max then fullstack := true
else fullstack := false ;
end ;
Function emptystack ( indic:top ) : boolean ; { stiv goal ?}
begin
if indic=0 then emptystack: = true
else emptystack := false ;
end ;
Procedure push (var st:stiva ; var indic:top ; elem:adresa ) ;
{ depune elemente n stiv }
begin
if not fullstack (indic) then
begin
st[indic] := elem ;
indic := indic+1 ;
end
else
begin writeln (stack overow) ;
exit ;
end;
end;
Function pop (st:stiva;var indic:top) : adresa ;
{ scoate elementele din stiv }
begin
5.2. Arbori de cutare 215
if not emptystack (indic) then
begin
indic := indic-1 ;
pop := st [indic] ;
end
else
begin writeln (stack underow) ;
exit ;
end ;
end ;
Procedure creare (rad : adresa) ; { creare rdcin vid}
begin
rad:=nil;
end;
Procedure inserare (var rad : adresa ; cheia : char ) ; { inserarea elementelor }
var
curent , nou : adresa ;
begin
if rad = nil then begin { inserare n cazul cnd arborele este vid }
new(nou) ;
nou.key := cheia ;
nou.weight := 0 ;
nou.lptr := nil ;
nou.rptr := nil ;
rad := nou ;
end
else begin { inserare n cazul cnd arborele nu este vid}
curent := rad ; tata := curent ;
while curent <> nil do
if cheia < curent.key then { inserarea ului stng al nodului curent }
begin
tata := curent ;
curent := curent.lptr ;
end
else if cheia > curent.key then { inserarea ului drept al nodului curent }
begin
216 5. Tehnici de cutare
tata := curent ;
curent := curent.rptr ;
end
else begin
writeln ( cheie dubl:eroare) ;
exit ;
end ;
new (nou) ; {inserarea propriuzis i actualizarea cmpurilor }
nou.key := cheia ;
nou.weight := 0 ;
nou.lptr := nil ;
nou.rptr := nil ;
if tata.key > cheia then tata.lptr := nou
else tata.rptr := nou ;
end ;
end ;
Procedure rebalansare (temp : adresa ; var tata : adresa) ; {rebalansarea arborelui}
var
bunic, t : adresa ;
begin
if temp.weight <= tata.weight then exit
else if (tata = root) then { interschimbarea nodului rdcin }
if temp.key < tata.key then
begin
tata.lptr := temp.rptr ;
temp.rptr := tata ;
root := temp ;
exit ;
end
else
begin
tata.rptr := temp.lptr ;
temp.lptr := tata ;
root := temp ;
exit ;
end
else
5.2. Arbori de cutare 217
t := pop (st,ind) ;
bunic := pop (st,ind) ;
if tata.key < bunic.key then
if temp.key<tata.key then
begin
bunic.lptr := temp ;
tata.lptr := temp.rptr ;
temp.rptr := tata ;
end
else
begin
bunic.lptr:=temp;
tata.rptr:=temp.lptr;
temp.lptr:=tata;
end
else
if temp.key<tata.key then
begin
bunic.rptr:=temp;
tata.lptr:=temp.rptr;
temp.rptr:=tata;
end
else
begin
bunic.rptr:=temp;
tata.rptr:=temp.lptr;
temp.lptr:=tata;
end;
push (st,ind,bunic) ;
tata:=bunic ;
rebalansare (temp,tata) ;
end ;
Function cautare ( rad : adresa ; cheiac : char ) : adresa ;
begin
temp := rad ; tata := rad ; reset (st,ind) ;
while (temp <> nil) and (temp.key <> cheiac) do
begin
if cheiac<temp.key then begin { se caut n subarborele stng }
218 5. Tehnici de cutare
tata:=temp;
push(st,ind,tata);
temp:=temp.lptr;
end
else begin { se caut in subarborele drept }
tata:=temp;
push(st,ind,tata);
temp:=temp.rptr;
end;
end;
if temp.key=cheiac then begin inc(temp.weight); { cheia este gsit }
writeln(Exista);
cautare:=temp;
rebalansare(temp,tata);
exit;
end
else
begin
cautare:=nil;
writeln(Nu exist);
end;
end;
Procedure sterg;
var u , predec , tatap : adresa ;
begin
if (temp.lptr=nil) and (temp.rptr=nil) then {tergerea unui nod terminal-
Cazul1}
if temp.key<tata.key then begin
tata.lptr:=nil;
dispose(temp);
end
else begin
tata.rptr:=nil;
dispose(temp);
end
else
if (temp.lptr = nil) XOR (temp.rptr = nil) then { tergerea unui nod cu un }
5.2. Arbori de cutare 219
begin { singur u Cazul 2, 3 }
if temp.lptr<>nil then u:=temp.lptr
else u:=temp.rptr;
if temp.key<tata.key then begin
tata.lptr:=u;
dispose(temp);
end
else begin
tata.rptr:=u;
dispose(temp);
end;
end
else begin {tergerea unui nod cu doi i Cazul 4}
predec:=temp;
tatap:=predec;
predec:=temp.lptr;
while predec.rptr<>nil do begin
tatap:=predec;
predec:=predec.rptr;
end;
temp.key:=predec.key;
temp.info:=predec.info;
if predec.lptr<>nil then tatap.lptr:=predec.lptr
else tatap.lptr:=nil;
dispose(predec);
end;
end;
Procedure stergere ( var rad : adresa ; cheias : char );
begin
temp:=cautare(root,cheias);
if temp<>nil then sterg
else begin
writeln(eroare-element inexistent);
exit;
end;
end;
220 5. Tehnici de cutare
Procedure preordine (var rad : adresa) ; { traversarea n preordine a arborelui}
begin
if rad<>nil then
begin
writeln (rad.key , : , rad.weight) ;
preordine (rad.lptr) ;
preordine (rad.rptr) ;
end ;
end ;
Procedure menu ;
begin
write (1-Inserare 2-Cutare 3-Aare 4-tergere );
write(5-Ieire);
end;
begin
menu;
creare(root);
repeat
ch := readkey;
case ch of
1:begin
writeln;
write(introducei cheia:);
readln(student.key);
inserare(root,student.key);
end;
2:begin
writeln;
write(introducei cheia cutat:);
readln(student.key);
cautare(root,student.key);
end;
3:begin
writeln(traversare preordine:);
preordine(root);
end;
4:begin
5.2. Arbori de cutare 221
writeln;
write(introducei cheia de sters:);
readln(student.key);
stergere(root,student.key);
end;
end;
until ch=5;
end.
5.2.4 Arbore de cutare 2-3 AC2-3
5.2.4.1 Descrierea general a arborelui de cutare 2-3
Un alt tip de arbore de cutare este arborele de cutare 23 (AC23). Un arbore
2-3 este denit ca un arbore de cutare n care nodurile non-frunz (neterminale)
au 2 sau 3 i, i toate nodurile frunz (terminale) au aceeai distan fa de nodul
rdcin.
Observaie. Un arbore care are un singur nod (nod frunz) este considerat a tot
AC2-3. Evident, arborii de cutare 2-3 nu sunt arbori binari, dei algoritmul de
cutare este pe undeva asemntor algoritmului de cutare binar.
Figura 5.14 ne prezint un exemplu de arbore 2-3 avnd inserate 5 date, cu cheile
de cutare 1, 3, 6, 7, 11. Celelalte noduri non-frunz sunt noduri pentru cutare.
11 7
7:11 1:3
6 3 1
6:11
Figura 5.15: Exemplu de arbore de cutare 2-3
222 5. Tehnici de cutare
ntr-un AC2-3 numai nodurile frunz conin date propriu-zise, celelalte noduri
(nodurile non-frunz) sunt noduri auxiliare de cutare.
Un nod non-frunz va denumit nod auxiliar de cutare. Un astfel de nod auxi-
liar de cutare va conine dou valori, corespunztoare limitei inferioare respectiv
limitei superioare a drumului de cutare [Aho, 1987].
Limita inferioar a unui nod auxiliar de cutare reprezint cea mai mare cheie
de cutare din subarborele stng. Limita superioar a unui nod auxiliar de cutare
reprezint cea mai mare cheie de cutare din subarborele mijlociu.
Observaie. Cnd un nod non-frunz (neterminal) are doar doi i, atunci se consid-
er c ul lips este ul din dreapta.
n cazul operaiilor de cutare, cheia de cutare este comparat cu cele dou valori
limit ale nodurilor auxiliare de cutare:
Dac cheia de cutare este mai mic sau egal cu limita inferioar de cutare,
atunci cutarea se face pe legtura u_stnga.
Dac cheia de cutare este strict mai mare dect limita inferioar de cutare,
dar mai mic sau egal dect limita superioar de cutare, atunci cutarea se
face pe legtura u_mijloc.
Altfel, dac cheia de cutare este mai mare dect limita superioar de cutare
i dac exist legtura u_dreapta atunci cutarea se face pe legtura
u_dreapta, altfel cutarea se face pe legtura u_mijloc .
5.2.4.2 Implementarea nodurilor AC2-3
Dup cum am vzut, un AC2-3 conine dou tipuri de noduri:
a. Nod auxiliar de cutare (non-frunz):
u_st a b tip u_mij u_st
Unde:
u_st : reprezint adresa ului stnga;
a: limita inferioar a drumului de cutare;
b: limita superioar a drumului de cutare;
tip: tipul nodului, nod auxiliar de cutare (non-frunz) tip = 1, nod de date
(frunz) tip = 0;
u_mij : reprezint adresa ului din mijloc;
u_dr : reprezint adresa ului dreapta;
5.2. Arbori de cutare 223
b. Nod de date (frunz):
tip cheia Alte_info
Unde:
tip: tipul nodului, nod auxiliar de cutare (non-frunz) tip = 1, nod de date
(frunz) tip = 0;
cheia: reprezint cmpul de date ales dup care este ordonat AC2-3;
Alte_info: alte informaii;
Structura nodului implementat n Pascal este:
Type
Tip_nod =(frunza, non-frunza);
adresa = Nod
Nod = record
case tag :Tip_nod of
frunza: (cheia : integer;
Alte_info : tip_info);
non-frunza: ( Fiu_stg : adresa;
a : integer;
b : integer;
u_mij : adresa;
u_dr : adresa;
end
5.2.4.3 Operaii ntr-un AC2-3
Operaiile n cazul arborilor de cutare 2-3 sunt urmtoarele:
a. creare-iniializare;
b. inserare;
c. cutare;
d. tergere;
e. traversarea:
Operaia de creare-iniializare este identic cu operaiile de la arborii binari de
cutare. Restul operaiilor sunt specice arborelui de cutare 2-3 i vor detaliate n
cele ce urmeaz.
224 5. Tehnici de cutare
b. Operaia de inserare.
Exist patru cazuri de analizat pentru operaia de inserare [Tre, 1984]. Acestea sunt:
Cazul 1. Arborele este vid. n acest caz alocm spaiu pentru noul nod frunz de
inserat i acesta va deveni noul nod rdcin.
Exemplu: n gura 5.16 a se insereaz nodul cu cheia 4.
4
9
4
4:9
b) a)
Figura 5.16: Cazul 1 de inserare a) i cazul 2 de inserare b)
Cazul 2. Arborele conine un singur nod (acesta coincide cu nodul rdcin). n
acest caz se creeaz un nou nod non-frunz care va deveni noul nod rdcin, vechiul
nod rdcin i noul nod de inserat vor deveni i nodului auxiliar de cutare.
Exemplu: n gura 5.16 b) se insereaz nodul cu cheia 9 n AC2-3 din gura 5.16
a).
Celelalte dou cazuri apar n situaia n care AC2-3 conine mai mult de un nod.
Regula n aceast situaie este urmtoarea: prima dat se determin locul unde ar
urma s e inserat noul nod, dup care este determinat nodul tat, avnd grij ca
s memorm drumul de cutare.
Cazul 3. Nodul tat are exact doi i. Inserm noul nod la n poziia determinat
de comparaia cheilor de cutare.
Dac valoarea cheii de inserat este mai mic dect valoarea cheii nodului u stnga,
atunci noul nod de inserat va deveni ul stng al nodului tat; dac valoarea cheii
nodului de inserat este mai mare dect cheia nodului u mijloc, atunci noul nod de
inserat va deveni nodul u dreapta al nodului tat; altfel noul nod de inserat va deveni
nodul u mijloc al nodului tat. Aceast nserare este prezentat n Figura 5.17.
Exemplu: n gura 5.17 b) se insereaz nodul cu cheia 9 n AC2-3 din gura 5.16
b).
Cazul 4. Nodul tat are trei i. n acest caz, noul nod de inserat ar deveni al
5.2. Arbori de cutare 225
patrulea u al nodului tat. Vom crea un nou nod non-frunz, nod frate cu nodul
tat. Poziia nodului nod frate este determinat de poziia i dispunerea nodurilor
u. Cele patru noduri i vor separate astfel: cei doi frai din stnga i cei doi frai
din dreapta vor ataai nodului tat iniial i nodului unchi nou creat.
Exemplu: n gura 5.17 se insereaz nodul cu cheia 9 n AC2-3 din gura 5.16 a).
9 4
4:9
9 7 4
4:7
Figura 5.17: Cazul 3 de inserare. n AC2-3 din stnga se insereaz un nou nod cu
cheia 7
11 9 7 4
4:7
7 11 9
9:11
4:7
7:11
4
4 9 7
4:7
Figura 5.18: Cazul 4 de inserare. n AC2-3 din stnga se insereaz un nou nod cu
cheia 11
Specicarea problemei de inserare, avnd ca date de intrare ROOT, cheia_nou,
info_nou, este urmtoarea:
DATE ROOT, cheia_nou, info_nou;
REZULTATE root;
226 5. Tehnici de cutare
Descrierea algoritmului de inserare n Pseudocod este:
ALGORITMUL INSERARE ESTE: { Se insereaz un nod nou }
CITETE cheia_nou, info_nou;
DAC ROOT = NIL ATUNCI { Cazul 1 de inserare }
CHEAM Creare_nod_frunza (cheia_nou, info_nou);
EXIT;
SFDAC
DAC ROOT.tip = 1 ATUNCI { Cazul 2 de inserare }
CHEAM Creare_nod_frunza (cheia_nou, info_nou);
{adresa noului nod = nou }
CHEAM Creare_nod_nonfrunza (nou, cheia_nou, info_nou);
{adresa noului nod = tata}
DAC ROOT.cheia < cheia_nou ATUNCI
tata.a := ROOT.cheia;
tata.b := cheia_nou;
tata.u_st := ROOT;
tata.u_mij := nou;
tata.u_dr := NIL;
ALTFEL
DAC ROOT.cheia > cheia_nou ATUNCI
tata.a := cheia_nou;
tata.b := ROOT.cheia;
tata.u_st := nou;
tata.u_mij := ROOT;
tata.u_dr := NIL;
ALTFEL
TIPRETE ( EROARE cheie dubl )
SFDAC
SFDAC
ROOT := tata ;
EXIT;
SFDAC
Tmp := ROOT ; { Cazul 3 sau 4 de inserare }
CTTIMP tmp.tip <> 0 EXECUT { Cutm nodul tat}
DAC cheia_nou < tmp.a ATUNCI
Push(stiva, top, tmp);
5.2. Arbori de cutare 227
tmp := tmp.u_st;
ALTFEL
Push(stiva, top, tmp);
tmp := tmp.u_mijl;
SFCT { Adresa nodului tat este n vrful stivei}
tata := pop(stiva, top);
Dac tata.u_dr := NIL
CHEAM Cazul_3_inserare (ROOT, tata, cheia_nou, info_nou);
ALTFEL
CHEAM Cazul_4_inserare (ROOT, tata, stiva, top, cheia_nou, info_nou);
SFALGORITM
Subalgoritmul Cazul_3_inserare este simplu de rezolvat. Se aloc spaiu pentru
noul nod de inserat, se compar cheia nodului de inserat cheia_nou cu limita inferioar
tata.a i limita superioar tata.b a nodului printe, inserndu-se n una din poziiile
u_st, u_mij, u_dr. Se actualizeaz corespunztor cmpurile nodului de inserat
i cmpurile nodului tat.
Subalgorimul Cazul_4_inserare poate schiat astfel n Pseudocod astfel:
SUBALGORITMUL Cazul_4_inserare (rad, t, st, virf, ch_n, info_n) ESTE:
@ Creeaz un nou nod non-frunz unchi, frate pentru nodul tat;
@ Distribuie cei 4 i ntre nodul tat i noul nod unchi;
@ Actualizeaz limita inferioar a, limita superioar b i legturile u_dr , u_mij,
u_st;
DAC @nodul printe nu are strmoi ATUNCI
@creeaz un nou nod rdcin;
@leag nodul printe de noul nod rdcin ca u stnga;
@leag noul nod unchi de noul nod rdcin ca u dreapta;
@actualizeaz cmpurile noului nod rdcin
EXIT
ALTFEL @extrage din stiva nodul tat al nodului tat; {nodul bunic}
@determin poziia de inserare al nodului unchi;
DAC @nodul bunic are numai doi i ATUNCI
@insereaz nodul unchi al nodului tat;
@actualizeaz cmpurile nodului unchi;
EXIT
ALTFEL CHEAM Cazul_4_inserare (rad, bunic, st, virf,
ch_n, info_n);
228 5. Tehnici de cutare
SFDAC
SFDAC
SF-Cazul_1
c. Operaia de cutare.
Specicarea problemei de cutare, avnd ca date de intrare ROOT i cheia_caut,
este urmtoarea:
DATE root, cheia_caut;
REZULTATE root;
Descrierea algoritmului de inserare n Pseudocod este:
ALGORITMUL CUTARE ESTE:
CITETE cheia_caut;
tmp := ROOT ;
CTTIMP tmp.tip <> 0 EXECUT {Pn cnd se ajunge la un nod terminal}
DAC cheia_caut < tmp.a ATUNCI
tmp := tmp.u_st;
ALTFEL
DAC ( tmp.a < cheia_caut ) i ( cheia_caut < tmp.b ) ATUNCI
tmp := tmp.u_mijl;
ALTFEL DAC tmp.u_dr <> NIL ATUNCI
tmp := tmp.u_dr;
ALFEL
TIPRETE (EROARE cheia cutat nu exist)
@returneaz NIL;
SFDAC
SFDAC
SFDAC
SFCT { Adresa nodului tat este n vrful stivei}
Dac tmp.cheia = cheia_caut ATUNCI
@returneaz adresa nodului gsit;
ALTFEL
@returneaz NIL;
SFDAC
SFALGORITM
5.2. Arbori de cutare 229
d. Operaia de tergere.
Specicarea problemei de tergere, avnd ca date de intrare ROOT i cheia_terg,
este urmtoarea:
DATE root, cheia_terg;
REZULTATE root;
Algoritmul de tergere presupune ntr-o prim faz gsirea nodului de ters i a
nodului tat al nodului de ters, dac acesta exist. Dac am gsit nodul de ters,
atunci va trebui s analizm n care din cazurile de mai jos ne situm:
Dac arborele conine un singur nod frunz, atunci algoritmul de tergere este
trivial:
Se actualizeaz adresa nodului rdcin care devine NIL;
Se elibereaz spaiul de memorie ocupat de nodul de ters.
Dac nodul tat al nodului de ters are 3 i, algoritmul de tergere este urm-
torul:
Se actualizeaz cmpurile nodului tat;
Se elibereaz spaiul de memorie ocupat de nodul de ters.
Dac nodul tat al nodului de ters are 2 i, algoritmul de tergere este urm-
torul:
Nodul rmas, frate al nodului de ters se leag de un nod unchi;
Dac nodul unchi avea 2 i, n urma alipirii nodului va avea 3 i;
Dac nodul unchi avea 3 i, n urma alipirii nodului va avea 4 i, deci va
trebui s facem:
2 Vom crea un nou nod non-frunz, nod frate cu nodul tat. Poziia
nodului nod frate este determinat de poziia i dispunerea nodurilor
u;
2 Cele patru noduri i vor separate astfel: cei doi frai din stnga i
cei doi frai din dreapta vor ataai nodului tat iniial i nodului
unchi nou creat.
Descrierea detaliat a algoritmului de tergere poate gsit n referina biblio-
grac [Aho, 1987].
230 5. Tehnici de cutare
e. Operaia de traversare.
Spre deosebire de arborii binari de cutare la arborii de cutare 2-3, datele propriu-
zise se gsesc pe acelai nivel sub form de noduri terminale. De aceea traversarea
AC2-3 este mai special necesitnd un test suplimentar, corespunztor deciziei dac
avem de-a face cu un nod terminal sau nu.
La fel ca la arborii de cutare, seciunea 4.5.2, cele trei modaliti de traversare
difer prin, momentul n care se viziteaz nodul rdcina i anume, n cazul:
- preordine: se viziteaz nti rdcina, apoi subarborele stng, subarborele din
mijloc i dup aceea subarborele drept dac exist;
- inordine: se viziteaz subarborele stng, se viziteaz rdcina, subarborele
din mijloc i subarborele drept dac exist, sau, se viziteaz subarborele stng,
subarborele din mijloc, se viziteaz rdcina i subarborele drept dac exist;
- postordine: se viziteaz subarborele stng, subarborele din mijloc, subarborele
drept dac exist i rdcina.
Descrierea algoritmilor de traversare, n limbajul Pascal este:
Procedure inordine_2_3 ( def : adresa ) ; { traversare inordine }
begin
if def <> NIL then
begin
inordine_2_3 ( def.u_st ) ;
if def.tip = 0 then
write ( def.cheia : 3 ) ;
inordine_2_3 ( def.u_mij ) ;
inordine_2_3 ( def.u_dr ) ;
end ;
end ;
Procedure preordine_2_3 ( def : adresa ) ; { traversare preordine }
begin
if def <> NIL then
begin
if def.tip = 0 then
write ( def.cheia : 3 ) ;
preordine_2_3 ( def.u_st ) ;
5.2. Arbori de cutare 231
preordine_2_3 ( def.u_mij ) ;
preordine_2_3 ( def.u_dr ) ;
end ;
end ;
Procedure postordine_2_3 ( def : adresa ) ; { traversare postordine }
begin
if def <> NIL then
begin
postordine_2_3 ( def.u_st ) ;
postordine_2_3 (def.u_mij);
postordine_2_3 ( def.u_dr ) ;
if def.tip = 0 then
write ( def.cheia : 3 ) ;
end ;
end ;
5.2.4.4 Performanele algoritmilor n AC2-3
Dac un AC2-3 are nlimea h, atunci numrul de noduri frunz este cuprins ntre
2
h
i 3
h
[Sed, 1990]. Aceasta nseamn c nlimea unui AC2-3 cu n noduri este cel
mult log
2
n, adic algoritmul de cutare este direct proporional cu O(log
2
n).
Probleme rezolvate
Exemplul 5.2.4. Implementarea PASCAL a operaiilor efectuate ntr-un AC2-3:
creare-iniializare, inserare, cutare.
Program Arbori_2_3;
Const max=100;
Type
str14 = string [14] ;
tip_nod = (terminal,neterminal);
adresa =nod ;
nod = record
case tag : tip_nod of
neterminal : (lkey : integer ;
lptr : adresa ;
232 5. Tehnici de cutare
mkey : integer ;
mptr : adresa ;
rptr : adresa ; ) ;
terminal : (key : integer ) ;
end ;
top = 0..max;
stiva = array [1..max] of adresa;
VAR head,tata:adresa;
STACK:stiva;
DIR:array [1..max] of char;
topdir ,valoare , nr :integer;
ind : top ;
p,nou : adresa ;
succes : boolean ;
c :char ;
Procedure reset_stack ; { iniializare stiv }
begin
ind := 0 ;
end ;
Function empty_stack ( ind:top ) : boolean ; { stiv goal }
begin
if ind = 0 then
empty_stack := true
else
empty_stack := false ;
end ;
Function full_stack ( ind : top ) : boolean ; { stiv plin }
begin
if ind = max then
full_stack := true
else
full_stack := false
5.2. Arbori de cutare 233
end ;
Procedure push ( var st : stiva ; var ind : top ; var element : adresa ) ;
{ introducere n stiv }
begin
if not full_stack ( ind ) then
begin
st [ ind ] := element;
ind := ind+1;
end
else
begin
writeln ( stack owerow ) ;
exit ;
end
end ;
Function pop ( var st : stiva ; var ind:top) : adresa ; { scoatere din stiv }
begin
if not empty_stack ( ind ) then
begin
ind := ind-1 ;
pop := st [ ind ] ;
end
else
writeln ( stack underow ) ;
exit ;
end ;
Function inform ( b:adresa ) : integer ; { funcia returneaz valoarea cheii }
begin
if b.tag = terminal then inform := b.key
else if b.rptr <> nil then inform := inform ( b.rptr )
else inform := inform (b.mptr) ;
end ;
234 5. Tehnici de cutare
Procedure Inserare_arbore ( nr:integer ) ;
Procedure Insert_caz1 ( x:integer ) ; { rdcina = nil }
var q : adresa;
begin
new (q ); { aloc memorie noului nod }
q.tag := terminal ;
q.key := x ;
head := q ;
succes := true ;
end ;
Procedure Insert_caz2 ( x:integer ) ; { arborele conine un singur nod }
var q,r,temp : adresa ;
begin
temp := head ;
new ( q ) ; q.tag := neterminal ;
if temp.key < x then begin
q.lkey := temp.key ; q.lptr := temp ;
new(r) ; r.tag := terminal ; r.key := x ;
q.mptr := r ; q.mkey := x ;
end
else begin
new(r) ; r.tag := terminal ; r.key := x ;
q.lkey := x ; q.lptr := r ;
q.mkey := temp.key ; q.mptr := temp ;
end ;
q.rptr := nil ;
head := q ;
succes := true ;
end;
Procedure Insert_caz3 ; { nodul tat are doi copii}
var q,temp1,temp2 : adresa;
begin
if (nr <> p.lkey ) and ( nr<>p.mkey ) then
begin
new ( q ) ;
5.2. Arbori de cutare 235
q.tag := terminal ;
q.key := nr ;
temp1 := p.lptr ;
temp2:=p.mptr;
if nr < temp1.key
then begin
p.lkey := nr ;
p.lptr := q ;
p.mkey := temp1.key ;
p.mptr := temp1 ;
p.rptr := temp2 ;
end
else if (temp1.key <nr) and (nr < temp2.key)
then begin
p.mkey := nr ;
p.mptr := q ;
p.rptr := temp2 ;
end
else p.rptr := q ;
succes := true ;
end ;
end ;
Procedure Caut_tata ;
begin
p := head ;
Push (stack,ind,p) ;
while p.lptr.tag = neterminal do begin
if nr <= p.lkey then begin
p := p.lptr ;
Push (stack,ind,p) ;
end
else if nr <= p.mkey then begin
p := p.mptr ;
Push (stack,ind,p) ;
end
else if p.rptr <> nil then begin
p := p.rptr;
236 5. Tehnici de cutare
Push (stack,ind,p);
end
else begin
p := p.mptr ;
Push (stack,ind,p);
end ;
end
end;
Procedure Insert_caz4 (nodnou:adresa); {nodul tat are 3 copii }
var tata,frate,temp1,temp2,temp3,newhead:adresa;
begin
tata := POP(stack,ind);
temp1 := tata.lptr ;
temp2 := tata.mptr ;
temp3 := tata.rptr ;
if ( temp3 = nil )
then
begin
if nr <= inform(temp1)
then
begin
tata.lkey := nr ;
tata.lptr := nodnou ;
tata.mkey := inform(temp1);
tata.mptr := temp1;
tata.rptr := temp2;
end
else if nr <= inform (temp2)
then begin
tata.mkey := nr;
tata.mptr := nodnou ;
tata.rptr := temp2 ;
end
else begin
tata.rptr := nodnou ;
end ;
end
5.2. Arbori de cutare 237
else
begin
new (frate) ; frate.tag:=neterminal;
if nr < inform (temp1)
then
begin
tata.lkey := nr;
tata.lptr := nodnou;
tata.mkey := inform(temp1);
tata.mptr := temp1;
tata.rptr := nil;
frate.lkey := inform(temp2);
frate.lptr := temp2;
frate.mkey := inform(temp3);
frate.mptr := temp3;
frate.rptr := nil;
end
else if nr < inform(temp2)
then
begin
tata.mkey := nr;
tata.mptr := nodnou;
tata.rptr := nil;
frate.lkey := inform(temp2);
frate.lptr := temp2;
frate.mkey := inform(temp3);
frate.mptr := temp3;
frate.rptr := nil;
end
else if nr < inform(temp3)
then
begin
tata.rptr := nil;
frate.lkey := nr ;
frate.lptr := nodnou ;
frate.mkey := inform(temp3) ;
frate.mptr := temp3 ;
frate.rptr := nil ;
238 5. Tehnici de cutare
end
else begin
tata.rptr := nil ;
frate.lkey := inform(temp3) ;
frate.lptr := temp3 ;
frate.mkey:= nr ;
frate.mptr := nodnou ;
frate.rptr := nil ;
end ;
if tata=head then begin
new (newhead) ;
newhead.tag := neterminal ;
newhead.lkey := inform(tata) ;
newhead.lptr := tata ;
newhead.mkey := inform(frate) ;
newhead.mptr := frate ;
newhead.rptr := nil ;
head := newhead ;
end
else Insert_caz4(frate) ;
end ;
end ;
begin
if head = nil then Insert_caz1(nr)
else if head.tag = terminal then begin
if head.key <> nr then Insert_caz2(nr)
end
else begin
caut_tata ;
if p.rptr = nil then Insert_caz3
else begin
if ( nr <> p.lkey) and (nr<>p.mkey) and
(nr<>p.rptr.key) then
begin
new(nou) ; nou.tag := terminal ;
nou.key := nr ;
Insert_caz4(nou) ;
5.2. Arbori de cutare 239
succes := true ;
end ;
end ;
end ;
if succes then begin
writeln ( OK ! ) ;
Indicator ;
end
else writeln( Eroare ! Cheie dubla ! ) ;
end;
Procedure Inserare ;
begin
writeln ;
write( Introduce informaia: ) ;
readln (valoare) ;
succes := false ;
reset_stack ;
Inserare_arbore(valoare) ;
end ;
Function caut(p:adresa;x:integer) : adresa ; forward ;
Procedure Cutare ;
var numar:integer;
adr : adresa ;
begin
write(Cheia de cutare: );
readln(numar);
adr:=caut(head,numr);
if adr=nil
then begin
writeln(Element inexistent !);
readln;
end
else begin
writeln(Cutare cu succes !);
writeln(Numrul: ,adr.key);
240 5. Tehnici de cutare
readln;
end;
end;
Function caut(p:adresa;x:integer):adresa;
begin
if p.tag =terminal
then if p.key=x
then caut:=p
else caut:=nil
else if x <= p.lkey
then caut:=caut(p.lptr,x)
else if (x > p.lkey) and (x <= p.mkey)
then caut:=caut(p.mptr,x)
else if p.rptr<>nil
then caut:=caut(p.rptr,x)
else caut:=nil;
end;
begin
clrscr;
writeln(1 - inserare 2 - cutare esc - iesire);
head:=nil;
repeat
c:=readkey;
case c of
1:begin
Inserare;
end;
2 :begin
Cutare;
end;
end;
until c=#27;
end.
5.3. Funcii de cutare hash 241
Probleme propuse
1. S se construiasc un arbore binar care cuprinde strmoii unei persoane, a
crui nume gureaz n rdcin arborelui. Nodul care gureaz n stnga
cuprinde numele tatlui, iar cel din dreapta pe cel al mamei. Fiind dat numele
unei persoane oarecare din familie, s se aeze numele bunicilor, dac acetia
gureaz in arbore.
2. Reprezentai grac arborele binar construit printr-o serie de inserri, pentru
urmtorul ir de chei: 8, 17, 10, 15, 5, 2, 16, 19, 13, 1 , 4, 11.
3. Dup ce n elemente au fost nserate ntr-un arbore, ntr-o ordine aleatoare, care
este numrul mediu de comparaii necesare pentru a gsi al m lea cel mai
mare numr ?
4. Demonstrai ca un AC2-3 de nlime h conine un numr de noduri terminale
cuprins ntre 2
h
i 3
h
.
5. Formulai un algoritm specic care terge i rebalanseaz un arbore binar ba-
lansat n greutate .
6. Formulai un algoritm care s modice un nod particular ntr-un ABCBG.
Apelul algoritmului s e de forma:
SCHIMB ( CHEIE , GREUTATE_NOU )
unde CHEIE este cheia nodului care se modic i GREUTATE_NOU este
noua greutatea a nodului.
Observaie. GREUTATE _NOU poate s aib o valoare care poate cauza
plasarea nodului la un nivel superior sau inferior n arbore.
5.3 Funcii de cutare hash
5.3.1 Introducere
Cea mai bun metod de cutare studiat pn acuma este cutarea binar, care
are timpul de cutare proporional cu O(log
2
n). Tehnicile de cutare discutate pn
acum se bazeaz exclusiv pe compararea cheilor.
O alt abordare posibil ar calculul direct al locaiei sau adresei unei date
cutate. Evident, ntr-un astfel de scenariu avem nevoie de o funcie special care s
transforme informaia corespunztoare cheii de cutare ntr-o adres unde s regsim
242 5. Tehnici de cutare
informaia cutat. Expresia de calcul este n mod natural dependent de mulimea
cheilor de cutare i de spaiul de memorie cerut de structura de date care va
stoca informaiile dorite. De exemplu, dac utilizm o alocare static cu ajutorul
unui tabel, pentru a nregistra date referitoare la cei n studeni a unei specializri,
atunci ecare student poate identicat printr-un numr, avnd valoare ntre 1 si
n. Dac cunoatem locaia a-i-a a studentului cutat atunci scrierea student[i] va
reprezenta accesul direct la datele studentului cutat. O astfel de relaie cheie-adres
exist rareori n aplicaii reale, deoarece n general cheile de cutare sunt alese fr
a se ine seama de consecinele implementrii ntr-un limbaj de programare a relaiei
cheie-adres.
Din punct de vedere matematic, aceasta problem de transformare a cheii ntr-
o adresa este denit ca o funcie, numit funcie hash H, care face maparea
spaiului de chei K ntr-un spaiu de adrese A. Funcia hash trebuie s genereze
o adres, pe baza unui calcul simplu aritmetic sau logic, efectuat asupra cheii n
totalitate sau asupra unei pri din cheie.
Datorit faptului c dimensiunea spaiului de chei este de obicei mai mare dect
dimensiunea spaiului de adrese, se poate ntmpla ca mai multor chei de cutare s le
corespund, prin intermediul funciei hash, o aceeai adres. Este evident implicaia
pentru funcia de hash, de a nu avea proprietatea de injectivitate, adic:
k
1
K, k
2
K, k
1
,= k
2
H(k
1
) = H(k
2
)
Acest fenomen se numete coliziune ntre nregistrrile memorate n structura de
date. Pentru a rezolva aceast problem este nevoie s analizm tehnici de re-
zolvare a coliziunilor, s construim algoritmi corespunztori care s ne permit
manipularea informaiilor stocate n structura de date.
Funciile hash se grupeaz n dou mari clase:
Funcii hash independente-distribuional;
Funcii hash dependente-distribuional.
Clasa de funcii hash independente-distribuional nu folosete distribuia cheilor
unei tabele pentru calculul adresei unei nregistrri.
Clasa de funcii hash dependente-distribuional se folosete de distribuia unor
chei, din punct de vedere probabilistic, pentru calculul adresei unei nregistrri.
S vedem n continuare cteva exemple de funcii hash, dup care vom analiza
operaiile i algoritmii corespunztori manipulrii nregistrrilor ntr-o structur de
date, precum i modaliti de a rezolva problema coliziunilor.
5.3. Funcii de cutare hash 243
5.3.2 Funcii hash
Vom examina o serie de funcii hash simple. Dou dintre proprietile funciilor hash
sunt importante, i anume:
viteza mare de calcul a adresei;
distribuia uniform a adreselor.
nainte de a trece la descrierea funciilor hash, s introducem conceptul de codi-
care a cheilor de cutare, numit uneori precondiionare. Codicarea cheilor
de cutare se refer la spaiul de chei K, care de cele mai multe ori este o mulime
alfanumeric, care nu permite aplicarea funciilor hash, care sunt funcii numerice.
De aceea, avem nevoie de codicare care face o transformare a mulimii cheilor de
cutare alfanumerice ntr-o mulime numeric care poate manipulat mai uor i
care poate argumentul funciilor hash numerice [Knu, 1976].
Cel mai des folosit exemplu de codicare se bazeaz pe utilizarea codurilor ASCII
sau EBCDIC, nlocuind semnicaia alfanumeric a unui caracter cu codul su nu-
meric corespunztor. De exemplu, putem folosi n locul caracterului alfanumeric A
numrul ntreg 11 care corespunde codului su ASCII.
O problem care poate apare datorit procesului de codicare este dimensiunea
prea mare a cheii numerice obinut prin procesul de codicare. Presupunnd ca
dimensiunea cheii de cutare este de 10 caractere alfanumerice, codicarea ar trans-
forma cheia de cutare alfanumeric ntr-o cheie de cutare numeric de ordinul miilor
de mii de miliarde, date care nu pot reprezentate n memoria calculatorului utilnd
metode clasice. De aceea, avem nevoie de o operaie pe care o vom numi scalare, care
s transforme intervalul [a, b] ntr-un interval [c, d]. Operaia de scalare se bazeaz pe
o transformare liniar de forma f : [a, b] [c, d], f(x) = x + , unde coecienii
i ai transformrii liniare se determin din sistemul:
_
_
_
f(a) = c
f(b) = d
(5.6)
5.3.2.1 Funcia hash - metoda mpririi
Una dintre cele mai utilizate funcii hash este cea bazat pe metoda mpririi.
Aceasta este denit n felul urmtor:
H : K A, H(x) = x mod m+ 1 (5.7)
244 5. Tehnici de cutare
unde m este un divizor ntreg nenul, iar operatorul mod este operatorul modulo,
adic restul mpririi lui x la m. Adresele generate de aceast funcie hash vor
1, 2, 3, . . ., m.
Funcia hash bazat metoda mpririi asigur, pn la o anumit limit, o dis-
tribuie uniform a mulimii adreselor generate. Aceast distribuie uniform prezint
ns dezavantajul producerii de coliziuni pentru cheile de cutare din aceeai clas de
echivalent modulo m.
5.3.2.2 Funcia hash - metoda ptratului mediu
O alt funcie hash care este folosit n multe aplicaii se bazeaz pe metoda ptra-
tului mediu. n aceast metod, cheia de cutare este ridicat la ptrat, iar adresa
unde va cutat nregistrarea este obinut prin alegerea unui numr de cifre sau
bii din mijlocul numrului obinut prin ridicare la ptrat. Numrul de cifre ales este
dependent de dimensiunea structurii de date care stocheaz nregistrrile cutate.
De exemplu, s considerm o cheie din ase cifre: 123.456. Ridicm la ptrat
i rezult numrul 15.241.383.936. Dac avem nevoie de o adres format din trei
numere, atunci putem alege poziiile din mijloc de la 5 la 7, deci adresa va 138.
5.3.2.3 Funcia hash - metoda ndoirii
Pentru funcia hash bazat pe metoda ndoirii , numrul corespunznd cheii de
cutare este divizat n numere de lungime egal cu dimensiunea spaiului de adresare,
cu o posibil excepie corespunznd ultimei pri, care se poate completa cu zerouri
nesemnicative pentru a avea aceeai dimensiune cu celelalte diviziuni. Aceste pri
sunt nsumate, este ignorat cifra carry, rezultatul adunrii formnd adresa dorit.
Observaie. Dac cheia este binar, vom folosi operaia logic XOR n locul oper-
aiei de adunare.
Exemplu. Cheia de cutare 356.942.781 este mprit n trei numere de cte trei
cifre pentru a forma o adres de trei cifre, deoarece spaiul de stocare necesit cel mult
999 de locaii de memorie. Cele trei numere obinute sunt 356, 942 si 781. Adunate,
obinem:
356 +
942
781
- - - - -
2079 renunm la cifra 2 de transfer i avem adresa 079.
5.3. Funcii de cutare hash 245
5.3.2.4 Funcia hash - metoda cifrelor
Funcia hash, bazat pe metoda cifrelor formeaz adrese prin selectarea i translatarea
cifrelor din cheia de cutare original.
Exemplu. O cheie de cutare ce are valoarea numeric 7.546.123 este transformat
n adresa 2164 prin selectarea cifrelor din poziiile 2 la 6 i inversarea ordinii lor.
Metoda de selectare i de inversare trebuie folosit cu consecven pentru o aceeai
mulime de chei de cutare. Pentru un set de chei aceeai poziie din cheie, aceeai
rearanjare trebuie folosit cu consisten.
5.3.2.5 Funcia hash - metoda dependent de lungimea cheii
O alta funcie hash des utilizat n structuri de date alocate static care folosesc tabele
este funcia hash bazat pe metoda dependent de lungimea cheii . n aceast
metod lungimea cheii este folosit singur sau mpreun cu o parte a cheii, pentru
a produce direct o adres din tabel, ori pentru a produce o cheie intermediar, care
este folosit mai departe cu o alt metod, cum ar de exemplu metoda mpririi,
pentru a genera o adresa nal din tabel.
O funcie hash de acest tip, sumeaz valoarea reprezentrii binare interne a primu-
lui i al ultimului caracter al cheii i a lungimii cheii, translatat la stnga cu patru
poziii binare (sau a multiplicat cu 2
4
= 16).
Exemplu. Avem cheia de cutare PROTEO. Ea va genera adresa:
215 + 214 + (6 16) = 525 dac utilizm codul EBCDIC.
Dac considerm 525 ca o cheie intermediar i aplicm metoda mpririi cu
divizorul 49, atunci adresa rezultat este 36.
5.3.2.6 Funcia hash metoda codicrii algebrice
Funcia hash bazat pe metoda codicrii algebrice are la baz teoria de codicare
algebric [Knu, 1976]. O cheie binar de n bii (k
1
k
2
. . . k
n
)
2
este codicat cu ajutorul
unui polinom de gradul n:
K(x) =
n

i=1
k
i
x
i1
(5.8)
Dac spaiul de adresare este n intervalul 0, 2
m
1|, atunci vom construi un polinom
divizor al polinomului K, i anume:
P(x) = x
m
+
m

i=1
p
i
x
i1
. (5.9)
246 5. Tehnici de cutare
mprind polinomul K la polinomul P, folosind operaii n baza 2, vom obine poli-
nomul rest:
R(x) = K(x) mod P(x) =
r

i=1
r
i
x
i1
. (5.10)
Coecienii polinomului rest R(x), (h
1
h
2
. . . h
r
)
2
vor genera adresa cutat.
5.3.2.7 Funcii hash - metoda multiplicativ
[Knu, 1976] a artat, ca funciile hash de cutare bazate pe metoda multiplicativ
sunt printre cele mai performante. Dac x Z
+
, iar c este o constant c pozitiv
subunitar, 0 < c < 1, atunci funcia hash arat n felul urmtor:
H(x) = mcx|| + 1 (5.11)
Am notat cu x| cel mai mare ntreg mai mic dect x i cu x| partea fracionar a
lui x.
Aceast funcie hash d rezultate foarte bune dac constanta c este aleas cores-
punztor. Alegerea constantei c este dicil.
5.3.3 Performana funciilor hash
[Knu, 1973] prezint studii asupra funciilor hash prezentate anterior. n general,
aceste funii hash genereaz adrese uniforme, dar o generalizare a acestei armaii
este dependent de mulimile particulare de chei de cutare.
Este nevoie de introducerea unui sistem de referin pentru a compara perfor-
manele diferitele funcii hash. Cel mai larg acceptat criteriu de referin este ALOS
(Average Length of Search), prezentat n (5.1).
De obicei, cea mai performant funcie hash de folosit pentru un anumit mulime
de cutare va minimiza ALOS. Sunt ns i ali factori, n afar de performana
funciilor hash, care minimizeaz ALOS, timpul mediu de cutare.
5.3.4 Tehnici de rezoluiune a coliziunilor
5.3.4.1 Introducere
Cu ajutorul funciilor hash se poate realiza transformarea cheie de cutare
adres. Nu am inut ns cont de problema prezentat n seciunea 5.3.1, i anume,
de problema coliziunilor. O coliziune apare, aa cum am mai artat, atunci cnd dou
chei de cutare distincte sunt mapate de funcia hash la aceeai adres a structurii
de date. n practic, un astfel de fenomen se ntmpl pentru c spaiul cheilor de
5.3. Funcii de cutare hash 247
cutare este mai mare dimensional dect spaiul adreselor. ntr-o astfel de situaie,
funcia hash nu este injectiv, deci dou sau mai multe chei de cutare pot genera,
prin intermediul funciei hash, aceeai adres. Evident c nu putem suprapune dou
sau mai multe nregistrri, cu chei de cutare diferite, la aceeai adres generat de
funcia hash.
Rezolvarea acestei probleme se face cu ajutorul tehnicilor de rezoluiune a
coliziunilor.
Tehnicile de rezoluiune a coliziunilor se mpart n dou clase:
adresare deschis;
adresare nlnuit.
Obiectivul general al tehnicilor de coliziune este de a ncerca plasarea nre-
gistrrilor aate n coliziune la alte adrese ale structurii de date. Dac structura
de date este o tabel, atunci ne propunem s plasm nregistrrile aate n tabel
n alte locaii libere ale tabelei. Aceasta va implica o serie de operaii de cutare n
tabel, pn cnd gsim o poziie liber, unde se poate insera una din nregistrrile
aate n coliziune.
Deci, avem nevoie de un mecanism i de algoritmul corespunztor care s exami-
neze toate poziiile structurii de date n vederea realizrii operaiilor de inserare,
cutare, tergere, actualizare. Un astfel de mecanism trebuie s satisfac o serie de
cerine, i anume [Tom, 1997]:
viteza (pentru a determina repede o nou poziie liber);
puterea de acoperire (pentru a putea cuta n toate poziiile existente n
structura de date);
reproductibilitatea (pentru a regsi nregistrrile inserate n structura de
date).
5.3.4.2 Tehnici de rezoluiune a coliziunilor prin adresare deschis
Ideea de baz n tehnica de rezoluiune a coliziunilor prin adresare deschis este de
a cuta pentru nregistrarea aat n coliziune o nou poziie liber n structura de
date. Dac structura de date este alocat static n memorie, atunci vom folosi o tabel
pentru reprezentare, tabela se va numi tabel hash. O astfel de tabel hash, ind
alocat static, are un numr nit de poziii de stocare a nregistrrilor, aceast capaci-
tate neputnd modicat pe parcursul execuiei programului ce implementeaz
algoritmul de manipulare a nregistrrilor. De aceea, pentru a folosi ct mai ecient
248 5. Tehnici de cutare
spaiul de stocare x oferit de o tabel hash, va trebui s facem disponibile toate
spaiile eliberate n urma unor operaii de tergere.
Putem a gestiona aceast problem, vom introduce marcaje care s ne indice
faptul c o poziie a tabelei hash este liber sau nu. Vom avea urmtoarele valori
posibile pentru o poziie liber din tabel hash, n cmpul cheii de cutare:
Emtpy poziie liber n tabela hash n care nu s-a inserat nici o nregistrare;
DELETED - poziie liber n tabela hash, unde a existat o nregistrare dar a
fost tears:
Mecanismul prin care realizm cutarea unei noi adrese pentru o cheie de cutare
aat n coliziune prin tehnica adresrii deschise este de mai multe feluri, i anume:
a. Probare liniar
b. Probare aleatoare
a. Probarea liniar
Unul din cele mai simple mecanisme de cutare a unei locaii libere pentru o nregi-
strare avnd o cheie de cutare n coliziune, este de a folosi o secven de cutare
liniar. Presupunnd c avem cheia k K, H(k) = a A, iar la adresa a avem
o coliziune, atunci probarea liniar se bazeaz pe urmtoarea secven de cutare
liniar:
a, a + 1, . . . , m1, m, 1, 2, . . . , a 1 (5.12)
unde m reprezint capacitatea maxim de stocare a tabelei. Vom gsi o locaie liber
dac tabela nu este deja plin.
Cnd efectum o operaie de cutare a unei nregistrri cu cheia de cutare k, vom
proceda astfel:
- calculm adresa corespunztoare cheii de cutare k : H(k) A;
- comparm cheia de la adresa a cu cheia de cutare k;
- Dac cheia de la adresa a este cea cutat, atunci avem o cutare cu succes:
- Dac cheia de la adresa a nu este cea cutat, pornim mecanismul de probare
liniar (5.12). Dac am ajuns la locaia de adres a 1, atunci cutarea nu
este cu succes, nregistrarea cutat nu exist n tabel. Altfel, cutarea este
cu succes.
5.3. Funcii de cutare hash 249
Aceast tehnic de rezolvare a coliziunilor se numete probare liniar.
Operaia de inserare este prezentat cu ajutorul unui exemplu. S presupunem c
avem o tabel de dimensiune 11 i cteva nregistrri cu urmtoarele chei de cutare
[Tre, 1986]:
NINA, STOICAN, ANA, ADA, FUNCTIE, B, BRAND i PARAMETRU
Aplicnd o funcie hash H, s presupunem ca avem urmtoarea situaie:
Cheia de cutare Adresa din tabela hash
NINA H(NINA) =1
STOICAN H(STOICAN) = 2
ANA H(ANA)=3
ADA H(ADA) = 3
FUNCTIE H(FUNCTIE) = 9
B H(B) =9
BRAND H(BRAND) =9
PARAMETRU H(PARAMETRU) = 9
Dup operaia de inserare, aplicnd mecanismul probrii liniare, vom avea urm-
toarea tabel:
Numrul de probe
Tabel [1] NINA 1
Tabel [2] STOICAN 1
Tabel [3] ANA 1
Tabel [4] ADA 2
Tabel [5] PARAMETRU 8
Tabel [6] Empty
Tabel [7] Empty
Tabel [8] Empty
Tabel [9] FUNCTIE 1
Tabel [10] B 2
Tabel [11] BRAND 3
Figura 5.19: Coninutul tabelei hash dup aplicarea operaiilor de inserare i a cutrii
unei noi poziii libere prin mecanismul de probare liniar
250 5. Tehnici de cutare
Primele trei nregistrri, avnd cheile de cutare, NINA, STOICAN, ANA sunt
inserate printr-o singur probare n primele trei poziii libere (Empty) ale tabelei.
nregistrarea cu cheia de cutare ADA trebuie plasat n poziia 4 a tabelei cci
poziia 3 este ocupat i astfel apare o coliziune. Este nevoie de dou probri.
nregistrarea cu cheia de cutare FUNCTIE este inserat n poziia 9 de la prima
operaie de probare cci poziia 9 din tabel era liber (Empty).
nregistrrile cu cheile de cutare B si BRAND, sunt n coliziune cu nregistrarea
cu cheia de cutare FUNCTIE, respectiv B. Pentru a insera nregistrarea cu cheia de
cutare B, aplicm mecanismul probrii liniare i obinem poziia liber 10 din tabel,
n urma a 2 operaii de probare. Pentru a insera nregistrarea cu cheia de cutare
BRAND, aplicm mecanismul probrii liniare i obinem poziia liber 11 din tabel,
n urma a 3 operaii de probare.
n nal, nregistrarea cu cheia de cutare PARAMETER va plasat prin meca-
nismul probrii liniare n poziia 5 a tabelei, necesitnd 8 operaii de probare, ind n
coliziune cu nregistrrile inserate anterior, ind probate poziiile ocupate 9, 10, 11,
1, 2, 3, 4 i poziia liber 5.
Specicarea problemei de inserare-cutare, avnd ca date de intrare tabela de hash
tab, dimensiunea maxim a tabelei m, cheia de inserare-cutare cheia, INS = 1 pentru
operaia de inserare i INS = 0 pentru operaia de cutare, este urmtoarea:
DATE tab, m, cheia, INS;
REZULTATE tab;
Descrierea algoritmului de inserare n Pseudocod este:
ALGORITMUL INSERARE_CUTARE_Probare_liniar ESTE:
CITETE cheia, INS;
a := H (cheia);
PENTRU i:=a;(m+a-1) MOD MAX EXECUT
{se genereaz adresele a, a+1,..,m}
{1,2,. . . , a-1 probare liniar }
DAC tab [i] = cheia ATUNCI
DAC INS = 0 ATUNCI
@returneaz adresa a {Cutare cu succes}
ALTFEL
TIPRETE (EROARE INSERARE cheie dubl, a);
EXIT;
SFDAC
5.3. Funcii de cutare hash 251
SFDAC
DAC (tab [i] = Empty) sau (tab [i] = DELETED) ATUNCI
DAC INS = 1 ATUNCI
@inserm noua nregistrare la adresa a din tabel
ALTFEL
DAC (tab [i] = Empty) ATUNCI
TIPRETE (EROARE CUTARE
inf. nu exist);
SFDAC
SFDAC
SFDAC
SFPENTRU
DAC INS = 0 ATUNCI
TIPRETE (EROARE CUTARE inf. nu exist);
ALTFEL
TIPRETE (EROARE INSERARE tabela plin);
SFALGORITM
Algoritmul de cutare implementat n limbajul Pascal, ca o funcie ce returneaz
adresa poziiei cutate din tabela hash, n cazul unei cutri cu succes, este:
Function search( key : typekey; var r : dataarray ) : integer;
var i, last : integer;
begin
i := hashfunction( key ) ;
last := (i+n-1) mod m;
while (i<>last) and (not empty(r[i])) and (r[i].k<>key) do
i := (i+1) mod m;
if r[i].k=key then search := i {*** nregistrarea a fost gsit ***}
else search := -1; {*** nregistrarea nu a fost gsit ***}
end;
Operaia de tergere a unei nregistrri din tabela hash este simpl. Vom cuta
nregistrarea de ters din tabela hash. Dac nregistrarea exist, vom avea grij
s marcm cmpul corespunztor cheii de cutare cu marcajul DELETED. Acest
marcaj este necesar pentru a optimiza operaiile de cutare care se opresc n cazul
unei cutri cu insucces dac avem valoarea marcajului DELETED, i pentru a evita
inserarea unor nregistrri cu cheie dubl. De exemplu, n tabela (5.19), dac tergem
252 5. Tehnici de cutare
nregistrarea cu cheia de cutare FUNCTIE i nu marcm cmpul cheie cu marcajul
DELETED, atunci dac vrem s nserm o nou nregistrare cu cheia de cutare
BRAND, poziia 9 din tabela hash va considerat liber i nregistrarea duplicat
va inserat.
Specicarea problemei de tergere, avnd ca date de intrare tabela de hash tab,
dimensiunea maxim a tabelei m, cheia de tergere cheia, este urmtoarea:
DATE tab, m, cheia;
REZULTATE tab;
Descrierea algoritmului de inserare n Pseudocod este:
ALGORITMUL TERGERE_Probare_liniar ESTE:
CITETE cheia;
adresa := INSERARE_CUTARE(tab, MAX, cheia, 0);
DAC adresa <= 0 ATUNCI
TIPRETE (EROARE CUTARE inf. nu exist);
ALTFEL
@marcheaz locaia de ters cu marcajul DELETED;
n lucrarea [Knu, 1976] gsim un model probabilistic pentru a analiza tehnicile de
rezoluie a coliziunilor i calculele pentru determinarea performanelor algoritmului
de cutare n cazul mecanismului de probare liniar. Modelul presupune ca ecare
cheie este echiprobabil pentru cutare. Dac notm cu m capacitatea maxim a
tabelei hash, atunci probabilitatea ca o nregistrare s e cutat este p
i
=
1
m
.
Dac dimensiunea spaiului cheilor de cutare este n, atunci vom avea un numr
de m
n
funcii posibile de la K la A.
Vom nota cu =
n
m
factorul de ncrcare a tabelei hash . Timpul mediu de
cutare va dependent de factorul de ncrcare. n [Knu, 1976] gsim urmtoarea
formul:
ALOS =
_

_
1
2
_
1 +
1
1
_
, pentru cutare cu succes
1
2
_
1 +
1
(1 )
2
_
, pentru cutare cu insucces
(5.13)
Pentru o distribuie uniform a mulimii cheilor de cutare, probarea liniar d
rezultate rezonabile, dac o comparm cu algoritmii de cutare secvenial sau
de cutare binar, presupunnd c tabela nu este plin. Factorul de ncrcare
5.3. Funcii de cutare hash 253
trebuie s e mai mic dect 0,8. Pentru o valoare mai mare a factorului de ncrcare
probarea liniara degenereaz rapid.
b. Probarea aleatoare
Metoda probrii liniare are o serie de dezavantaje. Un prim dezavantaj, este da-
torat faptului ca trebuie s gestionm un indicator suplimentar de tergere, numit
DELETED. n acest fel, o nregistrare oarecare din tabel are trei stri, i anume,
liber (Empty), ocupat sau tears (DELETED). n mod normal, ar trebui ca o
nregistrare din tabel s aib doar una din cele dou stri posibile, i anume, liber
sau ocupat.
Un alt dezavantaj al metodei de probare liniar este problema gruprii primare
(primary clustering). Acest fenomen apare datorit cutrii secveniale a unei poziii
libere pentru nregistrrile aate n coliziune. De aceea, nregistrrile aate n coli-
ziune tind s se grupeze ntr-o anumit poziie a tabelei, n loc ca ele s se distribuie ct
mai uniform, fenomen care duce la scderea performanelor algoritmului de cutare.
Efectele negative ale fenomenului gruprii primare, pot reduse prin selectarea
unei alte metode de probare, care s foloseasc un mecanism aleatoriu de cutare a
unei poziii libere n tabela hash, n loc de mecanismul de cutare secvenial. O astfel
de metod de probare se numete probare aleatoare (random probing)
Secvena de adrese de cutare pentru o poziie liber n tabela de hash va
generat aleator, dar va trebui s acopere toat mulimea de adrese cuprinse ntre
1 i m, exact o singur dat. O tabel de hash va plin, n momentul n care,
insernd o nou nregistrare, apelnd ca urmare a coliziunii la mecanismul de probare
aleatoare, se genereaz aleatoriu o adres duplicat [Tre, 1984].
Un exemplu de mecanism de generare aleatoare a adreselor pentru o tabel hash
este:
a := (a +c) mod m (5.14)
unde a este adresa iniial generat de funcia hash, c este o constant ntreag,
nenul, aleas astfel nct s e relativ prim cu m.
De exemplu, dac considerm c m = 11 i c = 5, atunci presupunnd c iniial
a = 2, atunci secvena de adrese generat pentru a cuta o poziie liber este 7, 1, 6,
0, 5, 10, 4, 9, 3, 8 i 2.
Specicarea problemei de inserare, avnd ca date de intrare tabela hash numit
tab, dimensiunea maxim a tabelei m, cheia de inserare cheia, este urmtoarea:
254 5. Tehnici de cutare
DATE tab, m, cheia;
REZULTATE tab;
Descrierea algoritmului de inserare n Pseudocod este:
ALGORITMUL INSERARE _Probare_aleatoare ESTE:
CITETE cheia;
a := H (cheia);
DAC (tab [i] = Empty) sau (tab [i] = DELETED) ATUNCI
@inserm noua nregistrare la adresa a din tabel;
CTTIMP @nu s-a gsit o poziie liber n tabela hash EXECUT
@calculeaz noua adres a utiliznd probarea aleatoare;
DAC @s-a generat o adres duplicat ATUNCI
TIPRETE (EROARE INSERARE tabela plin);
EXIT;
ALTFEL
DAC (tab [i] = Empty) sau (tab [i] = DELETED) ATUNCI
@inserm noua nregistrare la adresa a din tabel;
SFDAC
SFDAC
SFCT
SFALGORITM
Problemele legate de tergere devin i mai severe n cazul probrii aleatoare, dect
n cazul probrii liniare. Dei probarea aleatoare rezolv problema gruprii primare,
din pcate nu elimin problema gruprii secundare (secondary clustering). Gru-
parea secundar apare cnd se genereaz aceeai secven de adrese libere pentru
dou chei de cutare aate n coliziune.
O soluie pentru problema gruprii secundare, este de a folosii o funcie hash
secundar, care s genereze o valoare aleatoare pentru constanta c din formula (5.14),
independent de prima funcie hash. Prin aplicarea acestei metode se anuleaz efectul
negativ al gruprii secundare.
Fie H
1
: K A prima funcie de hash, i k
1
, k
2
K dou chei de cutare distincte
aate n coliziune, adic:
H
1
(K
1
) = H
2
(k
2
) = a A
Fie H
2
: K A a doua funcie de hash, folosit pentru a genera valoarea constan-
tei c din formula de probare aleatoare (5.14). Atunci dac H
2
(k
1
) ,= H
2
(k
2
) putem
5.3. Funcii de cutare hash 255
alege c = H
2
(k
1
). n acest fel, la ecare probare aleatoare se vor genera secvene
diferite de adrese, iar problema gruprii secundare va depit.
Metoda descris mai sus de a folosi dou funcii hash independente se numete
hash dublu.
Exemplu. S considerm urmtoarele funcii hash [Tre, 1984]:
H
1
(k) = k mod m i H
2
(k) = (k mod (m2)) + 1
unde k este valoarea cheii de cutare i m este mrimea tabelei hash. Pentru m = 11
i k
1
= 75 vom avea urmtoarele valori: H
1
(75) = 9 i H
2
(75)= 4.
Aplicnd formula probrii aleatoare (5.14), pentru a = 9 i c = 4, obinem secvena
de adrese n tabela hash: 9, 2, 6, 10, 3, 7, 0, 4, 8, 1, 5
Dac avem cheia de cutare k
2
= 42, atunci H
1
(42) = 9. Cheile de cutare k
1
i
k
2
sunt n coliziune. Alegnd c = H
2
(42) = 7, folosind formula de probare aleatoare,
obinem secvena de adrese n tabela hash: 9, 5, 1, 8, 4, 0, 7, 3, 10, 6, 2.
Implementarea n limbaj Pascal al algoritmului de cutare, utiliznd metoda hash
dublu este:
Function search( key : typekey; var r : dataarray ) : integer;
var i, inc, last : integer;
begin
i := hashfunction( key ) ; {prima funcie hash}
inc := increment( key ) ; {a doua funcie hash}
last := (i+(n-1)*inc) mod m;
while (i<>last) and (not empty(r[i])) and (r[i].k<>key) do
i := (i+inc) mod m;
if r[i].k=key then search := i {*** cutare cu succes ***}
else search := -1; {*** cutare fr succes ***}
end;
Performana algoritmului de cutare bazat pe probare aleatoare cu hash dublu, n
conformitate cu [Knu, 1976], este dat de urmtoarea formul:
ALOS =
_

ln(1 ), pentru cutare cu succes


1
1
, pentru cutare cu insucces
(5.15)
Metoda probrii aleatoare cu hash dublu este o metod mai performant dect
probarea liniar, n special cnd tabela hash este plin. De exemplu, cnd o tabel
256 5. Tehnici de cutare
hash are un grad de umplere de 95%, numrul mediu de operaii pentru metoda
probrii liniare este 10,5, pe cnd la metoda probrii aleatoare cu dublu hash este
3,2!
5.3.4.3 Tehnici de rezoluiune a coliziunilor prin adresare nlnuit
O alta metod de a rezolva problema coliziunilor este acea de a grupa cheile de cutare
aate n coliziune n clase de echivalen. Reprezentantul unei clase de echivalen va
capul unei liste simplu nlnuite cu ajutorul creia se vor gestiona dinamic toate
cheile de cutare aate n aceeai clas de coliziune, adic toate cheile de cutare care
genereaz aceeai adres:
H : K A, K =

k
1
,

k
2
, . . . ,

k
q
, k
i
, k
j


k
l
, dac H(k
i
) = H(k
2
) = k
i
.
Vom avea n acest fel o tabel hash x, de dimensiune m mai mare sau egal cu
numrul claselor de echivalen. n aceast tabel hash vom stoca doar cheia de
cutare reprezentant al clasei de echivalen i adresa de nceput a listei simplu n-
lnuite care stocheaz restul cheilor de cutare aate n coliziune cu cheia reprezen-
tant al clasei de echivalen.
Aceast tehnic de rezoluiune a coliziunilor se numete adresare nlnuit.
Exemplu. n gura de mai jos avem un exemplu de reprezentare a metodei adresrii
nlnuite, pentru m = 11 i n = 9. Presupunem c cheile sunt nserate n ordinea
urmtoare:
NINA , STOICAN , ANA , ADA , FUNCTIE , B , BRAND, PARAMETRU
S analizm algoritmul de inserare. Dac inserarm n structura noastr de date
nregistrri cu o cheie de cutare k, facem urmtorii pai:
Aplicm funcia hash i obinem adresa a pentru nregistrarea de inserat;
Cutm n tabela hash la adresa a existena unei alte nregistrri;
Dac poziia a din tabela hash este liber, nregistrarea de inserat nu este n
coliziune i crem primul nod al listei simplu nlnuite corespunztoare clasei
de echivalen a.
Dac poziia a din tabela hash este ocupat, nregistrarea de inserat este n
coliziune i inserm la sfritul listei simplu nlnuite noul element.
5.3. Funcii de cutare hash 257
Tabel [1] NINA
STOICAN Tabel [2]
ADA ANA Tabel [3]
Tabel [4]
Tabel [5]
Tabel [6]
Tabel [7]
Tabel [8]
Tabel [9]
Tabel [10]
Tabel [11]
B BRAND FUNCTIE PARAMETRU
Figura 5.20: Modelul de rezolvare a coliziunilor prin adresare nlnuit
Specicarea problemei de inserare, avnd ca date de intrare tabela hash numit
tab, dimensiunea maxim a tabelei m, cheia de inserare cheia, este urmtoarea:
DATE tab, m, cheia;
REZULTATE tab;
Descrierea algoritmului de inserare n Pseudocod este:
ALGORITMUL INSERARE _adresare_nlnuit ESTE:
CITETE cheia;
a := H (cheia);
DAC (tab [i] = Empty) ATUNCI
@inserm noua nregistrare la adresa a din tabel;
@inserare la sfrit lista simplu nlnuit;
ALTFEL
@inserare la sfrit lista simplu nlnuit;
SFDAC
SFALGORITM
258 5. Tehnici de cutare
Specicarea problemei de cutare, avnd ca date de intrare tabela hash numit
tab, cheia de cutare cheia_caut, este urmtoarea:
DATE tab, cheia_caut;
REZULTATE adresa;
ALGORITMUL CUTARE _adresare_nlnuit ESTE:
CITETE cheia_caut;
a := H (cheia_caut);
DAC (tab [i] = Empty) ATUNCI
TIPRETE (EROARE CUTARE inf. nu exist);
@returneaz NIL;
ALTFEL
adr := caut_list (LIST, cheia_caut);
{se caut n lista simplu nlnuit }
DAC adr = NIL ATUNCI
TIPRETE (EROARE CUTARE inf. nu exist);
@returneaz NIL;
ALTFEL
@returneaz adr;
SFDAC
SFDAC
SFALGORITM
Performana algoritmului de cutare bazat pe adresare nlnuit este, conform
cu [Tre, 1984]:
_

_
1 +

2
, pentru cutare cu succes
+e

, pentru cutare cu insucces


(5.16)
Capitolul 6
Tehnici de sortare
6.1 Istoric
Cutarea originii metodelor actuale de sortare ne conduce n secolul al XIX-lea, cnd
au fost inventate primele maini de sortat. n Statele Unite, cu ocazia recensmntului
din 1880, Herman Hollerith, angajat al Biroului de Recensmnt, a inventat o main
electric de tabelat pentru a rspunde necesitilor de prelucrare statistic. Un om
putea prelucra 49 de cartele pe minut. n 1901 a inventat o main mai modern care
lucra automat. Maina de sortat al lui Hollerith este baza metodelor de sortare dup
ranguri, folosite i n prezent pe calculatoare.
Ideea interclasrii provine de la o alt main cu cartele din anul 1938, numit
"collator", care putea interclasa dou pachete de cartele ntr-unul singur ntr-o singur
trecere.
Primul program scris pentru un calculator cu program memorat a fost o rutin
de sortare. John von Neumann a pregtit programe de sortare intern n 1945, pen-
tru a testa valabilitatea unor coduri de instruciuni propuse de el pentru calculatorul
ENIAC. Jonh Mauchly a confereniat despre "Sortare si Fuziune" la sesiunea special
asupra calculatoarelor inut la Moore School n 1946, iar notele acestei conferine
constituie prima discuie public a tehnicilor de sortare. Prima metod de sortare
folosea numrarea comparaiilor; apoi urmau o serie de treceri de interclasare echili-
brat cu dou ci.
n 1952 Daniel Goldenberg, a codicat 5 metode diferite: interclasarea direct cu
dou ci, sortarea cu baz 2, selecia direct, metoda bulelor. Seward a introdus idea
de numrare a distribuiilor i de selecie cu nlocuire.
Astfel, istoria sortrii este strns legat de multe premiere din domeniul calcula-
259
260 6. Tehnici de sortare
toarelor: primele maini de prelucrare a datelor primele programe memorate, primul
software, primele metode de utilizare a zonelor tampon de intrare-ieire, primele lu-
crri asupra analizei algoritmilor i asupra complexitii calculelor.
n 1959 Donald L. Shell a propus sortarea prin micorarea incrementului; sortarea
cu interclasare si interschimb a fost descoperit de K. E. Batcher n 1964; C. A.
R. Hoare a descoperit metoda sortrii rapide; n 1964 a fost descoperit sortarea cu
ansamble de ctre J. W. J. Williams. Pe parcursul anilor s-au mbuntit aceste
metode de sortare i s-au descoperit i metode noi, metode hibride.
6.2 Algoritmi de sortare
n acest capitol vom prezinta pe scurt cele mai importante informaii despre carac-
teristicile principalelor metode de sortare i a algoritmilor corespunztori, ncepnd
de la cele mai simple metode de sortare pn la cele complexe metode de sortare,
folosind diferite structuri de date: matrice, liste nlnuite, stive, arbori, . . . , etc.
Exist urmtoarea clasicare a metodelor de sortare [Lev, 1991]:
Metode de sortare simple: selecie, inserare, bule, Shell ;
Metode de sortare complexe: rapid, interclasare, ansamble, Radix.
Metodele simple de sortare au de obicei complexitatea O(N
2
), adic pot sorta
N elemente ntr-un timp proporional cu N
2
i sunt eciente pentru tabele mici n
care numrul de elemente este mai mic dect 500. Totui, pentru multe aplicaii
de sortare, este mai bine s folosim metode simple dect complexe. De exemplu,
dac tabela este deja sortat, n cazul metodei de sortare rapid, dac pivotul ales
(elementul n jurul creia se face sortarea) este primul element, metoda de sortare
prin selecie este mai rapid. Metodele simple sunt ntotdeauna mai potrivite pentru
un numr de elemente mai mic dect 50. Tabelele parial sau total sortate, sau cele
care conin un numr mare de chei identice, sunt relativ uor de sortat cu ajutorul
algoritmilor simpli. Necesit relativ puin timp de programare i ntreinere.
Metodele complexe pot sorta N elemente ntr-un timp proporional cu N log N.
Nici un algoritm nu poate folosi mai puin de N log N comparaii ntre chei. Aceste
metode complexe sunt eciente mai ales pentru sortarea unui numr mare de elemente.
Necesit mai mult timp pentru programare dar sunt mai eciente. Unul dintre cei mai
populari algoritmi de sortare cu scop general, este sortare rapid (Quicksort), care
are o complexitate de O(NlogN). Acest algoritm de sortare are performane bune n
general, chiar dac n caz nefavorabil complexitatea devine O(N
2
).
6.2. Algoritmi de sortare 261
Ideea "divide et impera" a fost aplicat problemelor de sortare n mai multe feluri,
rezultnd urmtorii algoritmii de sortare: rapid, interclasare, cu ansambluri, Radix
care sunt mult mai eciente dect cele simple. Sortarea cu ansambluri si sortarea prin
interclasare au complexitatea egal cu O(N log N), dei, n cazul general comportarea
lor nu este chiar aa de bun ca la algoritmul de sortare rapid. Exist metode care
folosesc proprietile digitale ale cheilor ca s obin o complexitate proporional cu
N, ca de exemplu sortarea Radix.
La baza studiului complexitii unui algoritm st detectarea, n descrierea algo-
ritmului a operaiei sau a operaiilor de baz, adic acele operaii aate n cel mai
interior corp de ciclu i a crei analiz permite estimarea n avans, nainte de lansarea
n execuie, a algoritmului ce descrie metoda de sortare respectiv.
n majoritatea cazurilor exist o legtur foarte strns ntre operaia de baz (cea
mai repetat operaie) i operaia care este dedus n etapa de analiz a problemei
ca ind operaia inevitabil pentru rezolvarea problemei.
De exemplu, n cazul problemei sortrii unui ir de N chei prin comparaii este
limpede c operaia de comparare a mrimii cheilor este operaia inevitabil i,
de asemenea, ea va i operaia de baz a crei contorizare va permite estimarea,
nainte de execuia programului ce implementeaz algoritmul, a duratei de execuie a
programului ce implementeaz algoritmul de sortare respectiv.
n aceast situaie, toi algoritmii diferii care soluioneaz aceeai problem i
care se bazeaz pe aceeai operaie de baz (inevitabil) formeaz clasa algoritmilor
de soluionare a problemei. De obicei, numele clasei va dat chiar de numele acelei
operaii de baz ce este coninut de ecare algoritm al clasei n mod inevitabil.
De exemplu, n cazul problemei sortrii unui ir de N chei prin comparaii, al-
goritmii diferii ce soluioneaz aceast problema sunt grupai n clasa algoritmilor
de sortare prin comparaie, spre deosebire de clasa algoritmilor de sortare prin dis-
tribuire ce soluioneaz aceeai problem bazndu-se ns pe alt operaie de baz:
distribuirea cheilor de sortat.
Astfel, algoritmi de sortare prin comparare descrii in aceasta lucrare sunt: al-
goritmul de sortare prin inserare, algoritmul de sortare prin selecie, algoritmul de
sortare Shell , algoritmul de sortare simplu, algoritmul de sortare rapid, algoritmul
de sortare cu ansambluri, algoritmul de sortare prin interclasare, iar algoritm de
sortare prin distribuire este algoritmul de sortare Radix.
Compararea ecienei a doi algoritmi diferii ce soluioneaz aceeai problem se
face prin determinarea teoretic a numrului de repetiii a operaiei de baz n ecare
algoritm si compararea celor dou valori. n nal, rezultatul va permite estimarea
comparativ a timpului de sortare a programelor ce implementeaz acei algoritmi
i alegerea celui mai bun algoritm.
262 6. Tehnici de sortare
Compararea ecienei a doi algoritmi, din punct de vedere practic, se face prin
compararea timpilor medii de execuie a celor dou programe ce i implementeaz.
Aceast metod pragmatic are dezavantajul c necesit rularea programelor care, n
anumite situaii, poate dura un timp surprinztor de mare.
Analiznd complexitatea algoritmilor, factorul cel mai important este timpul de
execuie exprimat prin "O-mare". Trebuie s folosim mai multe criterii pentru evalu-
area timpului de execuie al algoritmului de sortare cum ar , numrul de pai ai
algoritmului i numrul de comparaii dintre chei, necesare pentru a sorta N elemente.
Aceast msur este de folos cnd compararea dintre perechile de chei este costisitoare,
cnd cheile sunt iruri lungi de caractere, sau cnd mrimea nregistrrii este mare.
Al doilea factor important este cantitatea (volumul) de memorie suplimentar
folosit de un algoritm de sortare. Metodele se mpart n trei tipuri: cele care sorteaz
pe loc, nu folosesc memorie suplimentar, cu excepia poate unei tabele sau stive mici;
cele care au o reprezentare de list nlnuit, deci folosesc N cuvinte de memorie n
plus pentru pointerii listei; cele care au nevoie de memorie suplimentar pentru o
copie a tabelei iniiale.
Caracteristica care este uneori important n practic este stabilitatea. O metod
de sortare este stabil dac pstreaz ordinea relativ a cheilor egale n tabel. (Dac
sortm un ir de nume, numele cu aceeai liter de nceput sunt sortate n ordine
alfabetic). Majoritatea metodelor simple sunt stabile dar muli dintre algoritmii de
sortare compleci nu au aceast proprietate.
Metodele de sortare particulare nu sunt n totdeauna superioare metodelor de
sortare general, pentru orice set de chei. Proprietile unui set de chei joac un
rol important n alegerea algoritmului de sortare potrivit. Proprieti, ca numrul
de nregistrri, mrimea nregistrrii, distribuia i ordinea cheilor dicteaz des care
metod este de folosit. De exemplu, sortarea cu bule poate folosit dac numrul
elementelor din tabel este mic. Dac N este mare i cheile de comparat sunt mici,
mai performant este algoritmul de sortare Radix. Dac N este mare i cheile de
comparat sunt lungi, se poate folosi algoritmul de sortare rapid, algoritmul de sortare
prin interclasare, sau algoritmul de sortare cu ansambluri. Dac tabela iniial este
aproape sortat, algoritmul de sortare rapid nu are performane bune, algoritmul de
sortare prin inserare ind alegerea cea mai bun.
6.2. Algoritmi de sortare 263
ORDINEA DE MAGNITUDINE
ALGORITMUL
DE SORTARE Caz
Favorabil
Caz
General
Caz
Nefavorabil
SPAIUL
FOLOSIT
Sortare prin
selecie
O(N
2
) O(N
2
) O(N
2
) Sorteaz pe loc
Sortare cu bule O(N
2
) O(N
2
) O(N
2
) Sorteaz pe loc
Sortare cu bule,
"flag" mbuntit
O(N) O(N
2
) O(N
2
) Sorteaz pe loc
Sortare prin
inserare
O(N)
ir sortat
O(N
2
) O(N
2
) Sorteaz pe loc
Sortare Shell O(N
2
) O(N
2
) O(N
2
) Sorteaz pe loc
Sortare simpl O(N
2
) O(N
2
) O(N
2
) Sorteaz pe loc
Sortare rapid O(N log N) O(N log N)
O(N
2
) depinde
de ir i de
pivot
logN nregistrri
suplimentare
Sortare prin
interclasare
O(N log N) O(Nlog N) O(N log N)
N nregistrri
suplimentare
Sortare prin
ansambluri
O( Nlog N) O(Nlog N) O(N log N) Sorteaz n loc
Sortare Radix O(M+N) O(M+N)
Spaiu suplimentar
pentru legturi
Tabela 6.1: Compararea algoritmilor de sortare
264 6. Tehnici de sortare
6.2.1 Algoritmul de sortare prin metoda bulelor (bubble sort)
6.2.1.1 Descrierea general a metodei
S ne imaginm o tabel n poziie vertical care conine elemente (nregistrri) ne-
sortate. nregistrrile cu chei mici, ind mai uoare, asemenea bulelor de aer urc
spre vrful tabelei. Sortarea bulelor se bazeaz pe cutarea celui mai mare (mic) ele-
ment. Comparm elementele tabelei, dac dou elemente adiacente nu sunt n ordine
cresctoare, le interschimbm. Astfel, elementul cu cheia cea mai mare va ajunge
primul la locul potrivit, iar elementul cu cheia cea mai mic, urc tot timpul spre
vrful tabelei.
6.2.1.2 Descrierea algoritmului
Fie dat o tabel A cu N nregistrri R
i
, ecare nregistrare avnd cheia de cutare
K
i
. Pentru sortarea tabelei este nevoie de N-1 pai.
Parcurgem tabela n felul urmtor: comparm cheia primului element K
1
, cu cheia
celui de al doilea element K
2
si dac nu sunt n ordine cresctoare, interschimbm
primul element R
1
cu cel de-al doilea element R
2
.
Procesul se repet pentru nregistrrile R
2
, R
3
,. . . , R
N
. Dup prima parcurgere a
tabelei, nregistrarea cu cea mai mare cheie va ajunge pe ultima poziie N a tabelei.
n continuare vom lua n considerare primele N 1 nregistrri. Dup aceea vom
lua n considerare primele N 2 nregistrri, . . . , etc. Dup ecare pas, elementele
cu cheia cea mai mare va ajunge pe poziiile N 1, N 2, . . ., 2, n nal rezultnd o
tabel sortat n ordine cresctoare.
Exemplul 6.2.1. Sortarea tabelei A din Figura 6.1, n ordine cresctoare, folosind
algoritmul de sortare prin metoda bulelor:
Pasul 1: Prelucrm primele 10 nregistrri ale tabelei.
- comparm 6 cu 4, interschimbm;
- comparm 6 cu 5 i interschimbm:
- comparm 6 cu 10, nu interschimbm;
- comparm 10 cu 3, interschimbm;
- comparm 10 cu 1, interschimbm;
- comparm 10 cu 8, interschimbm;
- comparm 10 cu 9, interschimbm;
- comparm 10 cu 7, interschimbm;
- comparm 10 cu 2, interschimbm;
nregistrarea cu cheia cea mai grea, 10, a ajuns la partea inferioar a tabelei.
6.2. Algoritmi de sortare 265
Pasul 2: Prelucrm primele 9 nregistrri ale tabelei.
- comparm 6 cu 4, interschimbm;
- comparm 4 cu 5 i nu interschimbm:
- comparm 5 cu 6, nu interschimbm;
- comparm 6 cu 3, interschimbm;
- comparm 6 cu 1, interschimbm;
- comparm 6 cu 8, nu interschimbm;
- comparm 8 cu 9, nu interschimbm;
- comparm 9 cu 7, interschimbm;
- comparm 9 cu 2, interschimbm;
nregistrarea cu cheia cea mai grea, 9, a ajuns la partea inferioar a tabelei.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Algoritmul de sortare prin metoda bulelor ordoneaz cele 10 nregistrri ale
tabelei A n 8 pai.
Numrul pailor
J A[j] 1 2 3 4 5 6 7 8
1 6 4 4 4 3 1 1 1 1
2 4 5 5 3 1 3 3 3 2
3 5 6 3 1 4 4 4 2 3
4 10 3 1 5 5 5 2 4 4
5 3 1 6 6 6 2 5 5 5
6 1 8 8 7 2 6 6 6 6
7 8 9 7 2 7 7 7 7 7
8 9 7 2 8 8 8 8 8 8
9 7 2 9 9 9 9 9 9 9
10 2 10 10 10 10 10 10 10 10
Figura 6.1: Sortarea unei tabele A cu 10 elemente prin algoritmul de sortare prin
metoda bulelor
266 6. Tehnici de sortare
6.2.1.3 Implementarea algoritmului
Specicarea problemei de sortare, avnd ca date de intrare tabela A, dimensiunea
maxim a tabelei N, este urmtoarea:
DATE A, N;
REZULTATE A; { tabela A sortat n ordine cresctoare }
Descrierea algoritmului de sortare n Pseudocod este:
ALGORITMUL SORTARE_Bubble_sort ESTE:
CITETE A, N;
k := N;
REPET
Ok := TRUE;
PENTRU i := 1;k EXECUT
DAC A[i] > A[i+1] ATUNCI
temp := A[i];
A[i] := A[i+1];
A[i+1] := temp;
Ok := FALSE;
SFDAC
SFPENTRU
k := k -1;
PNCND Ok SFREP
SFALGORITM
Implementarea algoritmului de sortare prin metoda bulelor n limbajul Pascal
este:
Procedure bubble;
Begin
K := n;
Repeat
Ok := true;
For i := 1 to k do
If A[i] >A[i+1] then
Begin
6.2. Algoritmi de sortare 267
temp := A[i];
A[i] := A[i+1];
A[i+1] := temp;
Ok := false;
End;
k :=k-1;
Until Ok;
End;
6.2.1.4 Complexitatea algoritmului
Algoritmul de sortare prin metoda bulelor este o metod de sortare simpl, ecient
pentru un numr mic de elemente, dar nu i pentru tabele mari.
Nu necesit mult memorie, dar este de dou ori mai lent dect algoritmul de
sortare prin inserare, n aproape orice situaie. Timpul de execuie depinde de struc-
tura iniial a datelor de intrare, adic de ordinea iniial a elementelor [Ski, 1997].
Dac tabela de dimensiune N este deja sortat e nevoie de un singur pas, adic de
N-1 operaii de comparaie, n aceast situaie algoritmul ind de ordinul O(N).
n cazul cel mai nefavorabil sunt necesare N (N 1)/2 operaii de comparaie i
de N (N 1)/2 operaii de interschimbare. Complexitatea algoritmului de sortare
prin metoda bulelor este O(n
2
) n aceast situaie. Este o metod stabil.
Performana algoritmul de sortare se poate mbunti prin introducerea unei
variabile de tip boolean care ne arat cnd tabela este sortat, nainte de terminarea
numrului maxim de iteraii [Tom, 1997].
6.2.2 Algoritmul de sortare prin selecie
6.2.2.1 Descrierea general a metodei
Selecia direct este una dintre cele mai simple metode de sortare ce are performane
foarte bune pentru tabele mici, ecare element (nregistrare) a tabelei, ind mutat
n procesul de sortare cel mult o dat. Este o metod de sortare liniar, pentru
nregistrri lungi si chei de cutare mici. Implementarea algoritmului este simpl, dar
necesit spaiu de memorie destul de mare pentru a stoca dou tabele, acest lucru
ind un neajuns al algoritmului de sortare.
6.2.2.2 Descrierea algoritmului
Se caut cel mai mic element din tabela de sortat A i se schimb cu elementul de pe
prima poziie. Dup aceea se caut al doilea element minim si se schimb cu elementul
268 6. Tehnici de sortare
de pe poziia a doua, .a.m.d. n general, n pasul i se selecteaz elementul cu cea
mai mic cheie dintre nregistrrile A[i], A[i + 1], . . ., A[N] si se schimb cu A[i]. Ca
rezultat, dup i pai, al i-lea element minim va ocupa poziiile A[i], A[i +1], . . ., A[N]
n ordine sortat. Se continu pn cnd toate elementele vor sortate n ordine
cresctoare.
Exemplul 6.2.2. Sortarea tabelei A din Figura 6.2 folosind algoritmul de sortare
prin selecie, n ordine cresctoare:
A[j] 6 4 5 10 3 1 8 9 7 2
Pas1 1 4 5 10 3 6 8 9 7 2
Pas2 1 2 5 10 3 6 8 9 7 4
Pas3 1 2 3 10 5 6 8 9 7 4
Pas4 1 2 3 4 5 6 7 8 9 10
Pas5 1 2 3 4 5 6 8 9 7 10
Pas6 1 2 3 4 5 6 8 9 7 10
Pas7 1 2 3 4 5 6 7 9 8 10
Pas8 1 2 3 4 5 6 7 8 9 10
Figura 6.2: Sortarea unei tabele A cu 10 elemente prin algoritmul de sortare prin
selecie
Pasul 1: Prelucrm nregistrrile 1-10 ale tabelei.
- cutm nregistrarea cu cheia de cutare minim. Acesta este nregistrarea cu cheia
1 de pe poziia 6 a tabelei;
- interschimbm nregistrarea de pe poziia 1 cu nregistrarea minim de pe poziia 6;
nregistrarea cu cheia cea mai uoar, 1, a ajuns n poziia 1 a tabelei.
Pasul 2: Prelucrm nregistrrile 2-10 ale tabelei.
- cutm nregistrarea cu cheia de cutare minim. Acesta este nregistrarea cu cheia
2 de pe poziia 10 a tabelei;
6.2. Algoritmi de sortare 269
- interschimbm nregistrarea de pe poziia 2 cu nregistrarea minim de pe poziia
10;
nregistrarea cu cheia cea mai uoar, 2, a ajuns n poziia 2 a tabelei.
Pasul 3: Prelucrm nregistrrile 3-10 ale tabelei.
- cutm nregistrarea cu cheia de cutare minim. Acesta este nregistrarea cu cheia
3 de pe poziia 5 a tabelei;
- interschimbm nregistrarea de pe poziia 3 cu nregistrarea minim de pe poziia 5;
nregistrarea cu cheia cea mai uoar, 3, a ajuns n poziia 3 a tabelei.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Algoritmul de sortare prin metoda seleciei ordoneaz cele 10 nregistrri ale
tabelei A n 8 pai.
6.2.2.3 Implementarea algoritmului
Specicarea problemei de sortare, avnd ca date de intrare tabela A, dimensiunea
maxim a tabelei N, este urmtoarea:
DATE A, N;
REZULTATE A; { tabela A sortat n ordine cresctoare }
Descrierea algoritmului de sortare n Pseudocod este:
ALGORITMUL SORTARE_Inserie ESTE:
CITETE A, N;
PENTRU i := 1;N-1 EXECUT
min := i;
PENTRU j := i +1;N EXECUT
DAC A[j] < A[min] ATUNCI
Min := j;
SFDAC
SFPENTRU
temp := A[i];
A[i] := A[min];
A[min] := temp;
SFPENTRU
SFALGORITM
Implementarea algoritmului de sortare prin metoda seleciei n limbajul Pascal este:
270 6. Tehnici de sortare
Procedure selection (var A:arraytype; n:integer);
Var i, min:integer; {index }
Begin
For i := 1 to n-1 do
Begin
min := i;
For j := i+1 to n do
If A[j]<A[min] then min := j;
temp := A[i];
A[i] := A[min];
A[min] := temp;
End;
End;
6.2.2.4 Complexitatea algoritmului
Algoritmul de sortare prin metoda seleciei este o metod de sortare ecient pentru
un numr mic de elemente de sortat, dar nu pentru tabele mari.
Operaiile cele mai costisitoare sunt cele de cutare a nregistrrii cu cheia minim
din partea rmas nesortat n tabel. Dup ecare pas de cutare este necesar o in-
terschimbare, deci numrul interschimbrilor pentru N elemente este N1. Numrul
total de operaii de comparaie pentru a gsi cheia minim este [Knu, 1976]:
n1

i=1
(n i) = n(n 1) +
n(n 1)
2
=
n(n 1)
2
.
Atunci performana algoritmului de sortare prin metoda seleciei este O(n
2
). Aceleai
performane se obin i n medie i n cazul cel mai nefavorabil, chiar i atunci cnd
tabela este deja sortat. Dac avem nregistrri mari si chei mici, algoritmul de sortare
prin metoda seleciei va alegerea cea mai bun.
6.2.3 Algoritmul de sortare prin inserare
6.2.3.1 Descrierea general a metodei
Este un algoritm aproape la fel de simplu ca algoritmul de sortare prin selecie, dar
poate mai exibil.
Dac considerm c elementele A[1] . . . A[i 1] sunt deja sortate, atunci va trebui
s inserm elementul A[i] n locul potrivit pentru a menine ordinea de sortare aleas.
6.2. Algoritmi de sortare 271
6.2.3.2 Descrierea algoritmului
Fiind dat o tabel A cu N elemente nesortate, parcurgem tabela si inserm ecare
element n locul potrivit pentru a menine ordinea de sortare aleas ntre celelalte
elemente considerate deja sortate.
Pentru ecare i = 2 . . . N, dac elementele A[1], A[2], . . ., A[i] sunt sortate, vom
insera elementul A[i + 1] ntre lista elementelor sortate: A[1], A[2], . . ., A[i].
Elementele aate n stnga indexului i sunt sortate dar nu sunt nc n poziia lor
nal. Tabela este complet sortat cnd indexul ajunge la captul drept al tabelei.
Putem uura procesul inserrii (ex: cnd cel mai mic element e greu de denit), prin
introducerea unul element de "limit" A[0], cheia care va avea o valoare mai mic
dect orice valoare posibil a unei chei din tabel. Vom considera c aceast cheie
are valoarea .
Exemplul 6.2.3. Sortarea tabelei A din Figura 6.3 folosind algoritmul de sortare
prin inserare, n ordine cresctoare:
A[j] 6 4 5 10 3 1 8 9 7 2
Pas 1 4 6 5 10 3 1 8 9 7 2
Pas 2 4 5 6 10 3 1 8 9 7 2
Pas 3 4 5 6 10 3 1 8 9 7 2
Pas 4 3 4 5 6 10 1 8 9 7 2
Pas 5 1 3 4 5 6 10 8 9 7 2
Pas 6 1 3 4 5 6 8 10 9 7 2
Pas 7 1 3 4 5 6 8 9 10 7 2
Pas 8 1 3 4 5 6 7 8 9 10 2
Pas 9 1 2 3 4 5 6 7 8 9 10
Figura 6.3: Sortarea unei tabele A cu 10 elemente prin algoritmul de sortare prin
inserare
272 6. Tehnici de sortare
Pasul 1: Avem sortate nregistrrile dintre poziiile 1-1 ale tabelei.
- avem nregistrarea de pe poziia 2 cu cheia 4. Se caut poziia de inserare, care este
poziia 1;
- se insereaz cheia 4, naintea poziiei de inserare;
Secvena de chei din poziiile 1-2 ale tabelei sunt sortate.
Pasul 2 Avem sortate nregistrrile dintre poziiile 1-2 ale tabelei.
- avem nregistrarea de pe poziia 3 cu cheia 5. Se caut poziia de inserare, care este
poziia 2;
- se insereaz cheia 5, naintea poziiei de inserare;
Secvena de chei din poziiile 1-3 ale tabelei sunt sortate.
Pasul 3: Avem sortate nregistrrile dintre poziiile 1-3 ale tabelei.
- avem nregistrarea de pe poziia 4 cu cheia 10. Se caut poziia de inserare, care
este poziia 4;
- se insereaz cheia 10, naintea poziiei de inserare;
Secvena de chei din poziiile 1-4 ale tabelei sunt sortate.
Pasul 4: Avem sortate nregistrrile dintre poziiile 1-4 ale tabelei.
- avem nregistrarea de pe poziia 5 cu cheia 3. Se caut poziia de inserare, care este
poziia 1;
- se insereaz cheia 3, naintea poziiei de inserare;
Secvena de chei din poziiile 1-5 ale tabelei sunt sortate.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Algoritmul de sortare prin metoda inserrii ordoneaz cele 10 nregistrri ale
tabelei A n 9 pai.
6.2.3.3 Implementarea algoritmului
Specicarea problemei de sortare, avnd ca date de intrare tabela A, dimensiunea
maxim a tabelei N, este urmtoarea:
DATE A, N;
REZULTATE A; { tabela A sortat n ordine cresctoare }
Descrierea algoritmului de sortare n Pseudocod este:
6.2. Algoritmi de sortare 273
ALGORITMUL SORTARE_Inserare ESTE:
CITETE A, N;
A[0] := ;
PENTRU i := 2;N EXECUT
j := i;
CTTIMP A[j] < A[j -1]
temp := A[j];
A[j] := A[j -1];
A[j -1] := temp;
j := j -1;
SFCT
SFPENTRU
SFALGORITM
Implementarea algoritmului de sortare prin metoda inserrii n limbajul Pascal
este:
Procedure inserare ( var A: arraytype; n:integer);
Var i, j: integer;
Begin
A[0] := minus_innit; {minus_innit este o constant de valoare foarte mic}
For i:=2 to n do {i,j - variabila de tip index}
Begin
j := i;
While A[j]<A[j-1] do
Begin
temp := A[j];
A[j] := A[j -1];
A[j -1] := temp;
j := j-1;
End;
End;
End;
6.2.3.4 Complexitatea algoritmului
Algoritmul de sortare prin inserare este un algoritm de sortare liniar: complexitatea
algoritmului este O(N) pentru tabele care conin N elemente sortate sau aproape
274 6. Tehnici de sortare
sortate.
Complexitatea algoritmului de sortare prin inserare depinde de numrul de inserri
i translatri, care este inuenat de ordinea iniial al elementelor. n caz general
sunt necesare
N
2
4
operaii de comparaie i
N
2
8
operaii de interschimbare, deci ordinea
complexitii este O(N
2
) [Tre, 1984].
6.2.4 Algoritmul de sortare Shell
6.2.4.1 Descrierea general a metodei
Sortarea prin micorarea incrementului, numit i sortare Shell, este o extensie sim-
pl a metodei de sortare prin inserare, mbuntind performanele algoritmului prin
interschimbarea elementelor cele mai ndeprtate. Ideea de baz o constituie rearan-
jarea elementelor din tabela A n aa fel nct, lund ecare al h-lea element (ncepnd
de oriunde), s obinem o tabel sortat. Astfel, spunem c tabela este h-sortat. O
tabel h-sortat este format din h subtabele sortate independent. Folosind o proce-
dur pentru ecare secven de valori ale lui h, care se termin pentru valoarea 1, va
rezulta o tabel sortat.
S considerm tabela A i un increment mai mare dect 1, e acesta h. Vom avea
atunci urmtoarele subtabele:
Subtabelul1: A[1], A[h + 1], A[2h + 1], . . ..
Subtabelul2: A[2], A[h + 2], A[2h + 2], . . ..
Subtabelul3: A[3], A[h + 3], A[2h + 3], . . ..
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Subtabelul h: A[h], A[2h], A[3h], . . ..
Dac sortm ecare din cele h subtabele, folosind de exemplu algoritmul de sortare
prin inserare, atunci elementele ndeprtate se vor apropia, srind cu pasul h ctre
stnga. n nal, vom proceda la o sortare prin inserare cu incrementul 1, ceea ce
va necesita un timp foarte scurt cci tabela nu mai necesit corecii importante,
majoritatea nregistrrilor ind n poziia cresctoare dorit.
Algoritmul de sortare Shell , necesit o mulime de incremeni h
t
, h
t1
, . . . , h
1
,
ultimul increment h
1
ind egal cu 1.
O formula des utilizat n practic propune urmtoarele formule pentru secvena
de incremeni [Knu, 1976]:
h
1
= 1; h
i+1
= 3h
i
+ 1 (6.1)
Secvena este 1,4,13, 40, 121, . . . , cu formula general:
h
i
=
3
i
1
2
(6.2)
6.2. Algoritmi de sortare 275
Deci numrul total de incremeni va :
t = log
3
(2n + 1)| (6.3)
6.2.4.2 Descrierea algoritmului
Algoritmul de sortare Shell necesit mai multe operaii dect algoritmul de sortare
prin inserare, dar la ecare pas elementele ce urmeaz a interschimbate efectueaz
salturi lungi spre poziia corect, ceea ce ar trebui s duc la mbuntirea perfor-
manelor algoritmului de sortare.
n general, algoritmul de sortare Shell poate descris astfel [Aho, 1997]:
PENTRU k := t;1 EXECUT
PENTRU d := 0; h
k
1 EXECUT
CHEAM SORTARE_Inserare(@Subtabela d);
Exemplul 6.2.4. Sortarea tabelei A din Figura 6.4 (a) folosind algoritmul de sortare
Shell , n ordine cresctoare:
A[ ] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9] A[10] A[11] A[12]
(a) 11 10 9 8 7 6 5 4 3 2 1 0
(b) 11 6 1
10 5 0
9 4
8 3
7 2
(c) 1 6 11
0 5 10
4 9
3 8
2 7
(d) 1 0 4 3 2 6 5 9 8 7 11 10
(e) 0 1 2 3 4 5 6 7 8 9 10 10
Figura 6.4: Sortarea unei tabele A cu 12 elemente prin algoritmul de sortare Shell
276 6. Tehnici de sortare
Pasul 1 Crearea celor h subtabele (Fig. 6.4 (b))
- S presupunem c am ales incrementul h = 5. Se creeaz cele 5 subtabele:
Subtabela 1: 11, 6, 1
Subtabela 2: 10, 5, 0
Subtabela 3: 9, 4
Subtabela 4: 8, 3
Subtabela 5: 7, 2
Pasul 2 Sortarea celor 5 subtabele (Fig. 6.4 (c))
Pasul 3 Tabela iniial dup pasul de sortare cu incrementul 5 (Fig.6.4(d))
Pasul 3 Tabela iniial dup pasul de sortare cu incrementul 1 (Fig.6.4(d))
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ..
6.2.4.3 Implementarea algoritmului
Specicarea problemei de sortare, avnd ca date de intrare tabela A, dimensiunea
maxim a tabelei N, este urmtoarea:
DATE A, N;
REZULTATE A; { tabela A sortat n ordine cresctoare }
Descrierea algoritmului de sortare n Pseudocod este:
ALGORITMUL SORTARE_Shell ESTE:
CITETE A, N;
inc := Increment_intial(n);
CTTIMP inc >= 1 EXECUT
PENTRU i := inc; n-1 EXECUT
j := i;
x := A[i];
CTTIMP j >= inc i A[j - inc] > x EXECUT
A[j] := A[j - inc];
j := j - inc;
SFCT
A[j] := x;
6.2. Algoritmi de sortare 277
SFPENTRU
inc := Increment_urmtor(inc, n);
SFALGORITM
Observaie.
Secvena de incrementare este determinat iterativ, folosind funciile Incre-
ment_intial(n) i Increment_urmtor(inc, n). Funcia Increment_intial(n) va
returna cel mai mare increment utilizabil pentru sortarea unei tabele de dimen-
siune n.
Funcia Increment_urmtor(inc, n) va returna cel mai mare increment dar mai
mic dect inc, utilizabil pentru sortarea unei tabele de dimensiune n.
Funciile Increment_intial(n) i Increment_urmtor(inc, n) vor genera irul
descresctor de incremeni h
t
, h
t1
, . . . , h
1
= 1.
Se presupune c Increment_urmtor(1, n) = 0. Ciclul exterior se va termina
cnd inc = 1.
Implementarea algoritmului de sortare prin metoda inserrii n limbajul Pascal
este:
Procedure Shellsort ( var A: array[1.. N] of integer);
Var i, j, incr:integer;
Begin
incr := N div 2; { Funcia Increment_intial(n)}
While incr > 0 do
Begin
For i := 1 to incr do
Begin
k := i+incr;
While k<= N do
Begin
x :=A[k]; {x = elementul de comparat}
j := k-incr;
While j>0 do
Begin
If x.key < A[j].key then
Begin
278 6. Tehnici de sortare
Schimba (A[j+incr], A[j]);
j := j - incr;
End;
k := k+incr
End
End;
incr := incr div 2; {Funcia Increment_urmator(inc,n)}
End;
End;
End;
6.2.4.4 Complexitatea algoritmului
Complexitatea algoritmului de sortare Shell este greu de analizat, greu de comparat
cu alte metode, ind dependent i de mulimea de incremeni. Pentru acest algoritm
de sortare, cercetri empirice au artat c complexitatea este, n general O(N log N)
[Aho, 1997]. Exist mulimi de incremeni pentru care s-a dovedit c complexitatea
este O(N(log N)
2
). Nu se cunoate pn n prezent o mulime optimal de incremeni
pentru algoritmul de sortare Shell .
6.2.5 Algoritmul de sortare rapid (quicksort)
6.2.5.1 Descrierea general a metodei
Algoritmul de sortare, considerat a cel mai rapid, de complexitate O(N log N), este
algoritmul de sortare rapid (quicksort), folosind partiionarea ca idee de baz. Este
mai rapid dect orice metod de sortare simpl, se comport ecient pentru iere
sau tabele mari, dar inecient pentru cele de mici dimensiuni.
Strategia de baz are la baz o tehnic de tip "divide et impera" [Liv, 1986],
pentru c este mai uor de sortat dou tabele mici, dect o tabel mare. Algoritmul
este uor de implementat, consum mai puine resurse dect orice alt metod de
sortare.
6.2.5.2 Descrierea algoritmului
Avnd o tabel A cu N elemente, alegem o cheie pivot v n jurul creia rearanjm
elementele. Pivotul poate ales n mai multe moduri. O modalitate simpl ar s
alegem ca pivot primul element.
6.2. Algoritmi de sortare 279
Dup ce avem pivotul, partiionm tabela. Prin partitionare toate elementele cu
chei mai mici dect pivotul le vom plasa n partiia stng a tabelei, iar elementele
cu chei mai mari dect pivotul n partiia dreapt.
Dup aceea, apelm recursiv algoritmul de sortare rapid relativ la cele dou
subtabele formate prin partiionare.
Se consider urmtoarea schem de comparaie-interschimb:
folosindu-se 2 indicatori i, j, cu valorile iniiale i = 1 i j = N, se compar
nregistrarea cu numrul de ordine i cu nregistrarea cu numrul de ordine j;
algoritmul mut pe i la dreapta, pn cnd gsete o cheie mai mare dect
pivotul v si mut pe j la stnga pn cnd gsete o cheie mai mic dect
pivotul v.
dac nu este necesar interschimbarea se decrementeaz j cu 1 si se repet
procesul de comparaie;
dac apare un interschimb, se incrementeaz i cu 1 si se continu compararea,
mrind i pn la apariia unui nou interschimb;
se decrementeaz j, continundu-se acest proces de numit "ardere a lumnrii
la ambele capete", pn cnd i >= j.
Procedura se apeleaz recursiv printr-un apel de forma: SORTARE_Rapida(A,1, N);
Exemplul 6.2.5. Sortarea tabelei A din Figura 6.4 (a) folosind algoritmul de sortare
Shell , n ordine cresctoare:
Pasul 1: Alegem pivotul, elementul cu cheia 7 de pe poziia 1
- Comparm pe 7 cu 4, 7 > 4, i interschimbm;
Pasul 2: Caut de la stnga la dreapta elementul cu cheia mai mare dect
7 (indexul i)
- Acesta este 8, comparm pe 7 cu 8, 8 > 7, i interschimbm;
Pasul 3: Caut de la dreapta la stnga elementul cu cheia mai mic dect
7 (indexul j)
- Acesta este 6, i interschimbm cu elementul de pe poziia i;
Procesul de "ardere a lumnrii la ambele capete" se continu pn cnd i >= j,
atunci tabela se mparte n dou subtabele care se sorteaz separat recursiv pn
cnd ecare subtabel va conine doar un element.
280 6. Tehnici de sortare
7 5 8 2 3 9 1 6 4
i j
4 5 8 2 3 9 1 6 7
i j
4 5 7 2 3 9 1 6 8
i j
4 5 6 2 3 9 1 7 8
i j
4 5 6 2 3 7 1 9 8
i j
4 5 6 2 3 1 7 9 8
j = i
4 5 6 2 3 1 7 9 8
i j i
j
1 2 3 4 5 6 7 8 9
SCHIMBA(4,1)
STOP
SCHIMBA(7,1)
SCHIMBA(9,7)
SCHIMBA(7,6)
SCHIMBA(8,7)
SCHIMBA(7,4)
Figura 6.5: Sortarea unei tabele A cu 12 elemente prin algoritmul de sortare Shell
6.2.5.3 Implementarea algoritmului
Specicarea problemei de sortare, avnd ca date de intrare tabela A, dimensiunea
maxim a tabelei N, este urmtoarea:
DATE A, N;
REZULTATE A; { tabela A sortat n ordine cresctoare }
Descrierea general a algoritmului de sortare n Pseudocod este:
ALGORITMUL SORTARE_Rapid (i , j) ESTE:
DAC @ntre A[i] i A[j] exist cel puin dou chei distincte ATUNCI
@e v := cea mai mare dintre cele dou chei distincte;
@permutm A[i], . . . ., A[j] astfel nct pentru i + 1 k j s avem:
6.2. Algoritmi de sortare 281
elementele A[i], . . . ., A[k-1] au chei strict mai mici dect pivotul v;
elementele A[k], . . . ., A[j] au chei mai mari sau egale cu pivotul v;
CHEAM SORTARE_Rapid (i , k-1)
CHEAM SORTARE_Rapid (k , j)
SFALGORITM
Implementarea algoritmului de sortare prin metoda rapid n limbajul Pascal
este:
Variabilele left si right reprezint nceputul si sfrsitul tabelei sau subtabelei.
Procedure QUICK(left, right: integer);
Var i,j: integer;
v, t: elem;
Begin
i := left; j := right; v := A[l];
Repeat
While A[i].key < v.key do
i := i+1;
While A[j].key > v.key do
j := j-1;
If i < j then
Begin
t := A[i];
A[i] := A[j];
A[j] := t;
End
Until i >= j {pentru siguran; conform algoritmului era sucient i = j}
If left < j-1 then
QUICK (left, j-1);
If i+1 < right then
QUICK (i+1, right);
End;
6.2.5.4 Complexitatea algoritmului
n algoritmului de sortare rapid, ecare element este comparat cu pivotul, adic
avem complexitatea O(N).
282 6. Tehnici de sortare
n continuare, tabela este divizat n dou pri, ecare parte este iari divizat
n dou pari, . . . ., .a.m.d. Dac ecare parte este mprit aproximativ n dou
jumti egale, vom avea log
2
N operaii de mprire.
Deci complexitatea algoritmului de sortare rapid este n caz mediu O(N log
2
N),
iar n caz nefavorabil este O(N
2
) [Knu, 1976].
Dup cum am artat mai sus, algoritmul de sortare rapid este o metod bun n
cazul general, dar nu i n cazul nefavorabil, cnd este preferabil alegerea pivotului
conform formulei (6.2). Performanele algoritmului de sortare rapid sunt dependente
de ordinea datelor de intrare. De aceea, nu este o metod de sortare stabil.
6.2.6 Algoritmul de sortare prin interclasare (mergesort)
6.2.6.1 Descrierea general a metodei
Algoritmul de sortare prin interclasare se bazeaz pe urmtoarea idee: pentru a sorta
o tabel cu Nelemente o mprtim n dou tabele pe care le sortm separat i le
interclasm. Este o metod de sortare care foloseste strategia de baz "divide et
impera", conform creia problema se descompune n alte dou subprobleme de acelai
tip i dup rezolvarea lor rezultatele se combin. Algoritmul sorteaz elementele n
ordine cresctoare.
6.2.6.2 Descrierea algoritmului
Fiind dat o tabel A cu N elemente, tiem (sau mprtim) tabela n dou prti,
sortm separat ambele pri i mbinm cele dou jumtti ntr-o tabel auxiliar
temporar. Dac o jumtate are doar un element, o consoderm deja sortat. Tierea
n dou a tabelei nseamn gsirea punctului de mijloc: (prim+ultim)div2.
Pentru a "mbina" jumtile sortate, interclasm ecare subtabel, comparm
succesiv perechile de chei (din ecare parte) i punem valoarea mai mic ntr-o tabela
temporar. Algoritmul necesit urmtorii pai:
1. mparte tabela n dou
2. Sorteaz jumtatea stng
3. Sorteaz jumtatea dreapt
4. mbin prin interclasare cele dou jumti sortate ntr-o tabel sortat.
mbinarea celor dou pri necesit un numr de operaii de ordinul O(N). Al-
goritmul se termin cnd o subtabel nu mai are nici o nregistrare si mutm nre-
6.2. Algoritmi de sortare 283
gistrrile rmase din cealalt subtabel n tabela temporar. Dup pasul de inter-
clasare putem copia tabela temporar sortat n tabela original.

N = 50
N = 50
[100]
N = 100 A
[1]
[1] [50] [51] [100]
Figura 6.6: "mbinarea" prin interclasare a unei tabele A cu 100 elemente
Pasul 1: Am mijlocul tabelei
- mijloc := (1 + 9) / 2 = 5;
Pasul 2 mprim tabela n dou subtabele fa de elementul de mijloc.
- avem subtabela format din nregistrrile 7, 5, 8, 2;
- avem subtabela format din nregistrrile 3, 9, 1, 6, 4;
Pasul 3: Sortm subtabela stng.
- avem nregistrrile cu cheile sortate: 2, 5, 7, 8.
Pasul 4: Sortm subtabela dreapt.
- avem nregistrrile cu cheile sortate: 1, 3, 4, 6, 9.
Pasul 5: Interclasm subtabela stng i dreapt n tabela Temp.
Pasul 6: Copiem nregistrrile din tabela Temp n tabela original A.
6.2.6.3 Implementarea algoritmului
Specicarea problemei de sortare, avnd ca date de intrare tabela A, dimensiunea
maxim a tabelei N, este urmtoarea:
284 6. Tehnici de sortare
Tabela A:
7 5 8 2 3 9 1 6 4
2 5 7 8 1 3 4 6 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
right
first
left
last
left
first
Subtabela 1 Subtabela 2
Temp
right
last
A
Figura 6.7: Sortarea unei tabele A cu 9 elemente prin algoritmul de sortare prin
interclasare
DATE A, N;
REZULTATE A; { tabela A sortat n ordine cresctoare }
Descrierea general a algoritmului de sortare n Pseudocod este:
ALGORITMUL SORTARE_Interclasare ESTE:
CITETE A, N;
Index := PrimStng;
CTTIMP @mai sunt elemente n jumtatea stng si n cea dreapt
DAC cheia_Index_curent_stng < cheia_Index_curent_drept
ATUNCI
Temp[Index] := A[Index curent stng]
Index_curent_stng := Index_curent_stng + 1;
ALTFEL
Temp[Index] := A[Index curent_ drept];
Index_curent_drept := Index_curent_drept + 1;
@Copiaz toate elemente rmas din jumtatea stng n tabela Temp;
@Copiaz toate elemente rmas din jumtatea deapt n tabela Temp;
@Copiaz toate elemente sortate din tabela Temp n tabela A;
6.2. Algoritmi de sortare 285
SFALGORITM
Implementarea algoritmului de interclasare n limbajul Pascal este:
Variabilele lrst, llast, rrst, rlast indic cele dou capete ale subtabelei din stnga
si ale subtabelei din dreapta. Variabilele curent_left si curent_right reprezint ele-
mentul curent din stnga respectiv din dreapta. Temp este tabela temporar folosit
pentru sortare.
Procedure Interclasare (var A:arraytype; lrst, llast, rrst, rlast: integer);
var
temp: arraytype;
index, curent_left, curent_right: integer;
Begin
curent_left:=lrst;
curent_right:=rrst;
index:=lrst;
While (curent_left<=llast) and (curent_right<=rlast) do
Begin
If A[curent_left]< A[curent_right] then
Begin
Temp[index]:=A[curent_left];
curent_left:=curent_left+1;
End
Else
Begin
Temp[index]:=A[curent_right];
curent_right:=curent_right+1;
End;
index := index+1;
End;
While curent_left<=llast do
Begin
Temp[index]:=A[curent_left];
curent_left:=curent_left+1;
index:=index+1;
End;
While curent_right<=rlast do
286 6. Tehnici de sortare
Begin
Temp[index]:=A[curent_right];
curent_right:=curent_right+1;
index:=index+1;
End;
For index:=lrst to rlast do
A[index] := Temp[index]
End;
Implementarea algoritmului de sortare prin interclasare, varianta recursiv, n
limbajul Pascal este:
Procedure SORTARE_Interclasare (var A: arraytype; rst,last:integer);
var
middle: integer;
Begin
If rst < last then
Begin
middle:=(rst+last) div 2;
SORTARE_Interclasare (A, rst, middle);
SORTARE_Interclasare (A, middle +1, last);
Interclasare (A, rst, middle, middle +1, last);
End;
End;
6.2.6.4 Complexitatea algoritmului
Majoritatea operaiilor efectuate de algoritmul de sortare prin interclasare sunt efec-
tuate de operaiile de comparare i de copiere.
n cadrul operaiilor de interclasare, ecare nregistrare din cele dou subtabele
este comparat, aceast nsemnnd o complexitate de ordinul O(N).
Copierea nregistrrilor din tabela temporar Temp n tabela original A necesit
un numr de operaii tot de ordinul O(N).
Procedura de sortare propriu-zis este recursiv i este apelat recursiv pentru
jumtatea stng i pentru jumtatea dreapt. Tabela iniial A poate mprit
de cel mult log
2
N ori. La ecare mprire se execut operaia de interclasarere care
este de ordinule O(N).
6.2. Algoritmi de sortare 287
Atunci algoritmul de sortare prin interclasare va avea o complexitate de ordinul
O(N log
2
N) n toate dintre cele trei cazuri [Tom, 1997]. Este o metod stabil. Algo-
ritmul de sortare prin interclasare nu este dependent de ordinea iniial a elementelor.
Dezavantajul algoritmului de sortare prin interclasare este c necesit o tabel
auxiliar Temp de dimensiune N egal cu dimensiunea tabelei de sortat A.
6.2.7 Algoritmul de sortare prin ansambluri (heapsort)
6.2.7.1 Descrierea general a metodei
Deniia 6.2.1. Un arbore binar posed proprietatea de ansamblu dac orice
nod al su veric proprietatea: cheia de cutare a nodului tat este mai mare sau
egal dect cheia de cutare a nodului u_stnga sau dect cheia de cutare a nodului
u_dreapta.
Deniia 6.2.2. Un ansamblu (heap) este un arbore binar complet ce posed
proprietatea de ansamblu (Deniia 6.2.1).
Caracteristica de baz a acestei structuri de date, numit ansamblu, este c
modicarea valorii cheii de cutare a unui nod se poate face uor pstrnd totui
proprietatea de ansamblu. Presupunnd c cheia de cutare a unui nod_u de-
pete cheia de cutare a nodului_tat, este sucient s interschimbm ntre ele cele
dou noduri, s continum procedeul pe drumul ascendent ctre nodul rdcin, pn
cnd proprietatea de ansamblu este restabilit. Vom spune c valoarea modicat
a fost ltrat ctre noua poziie [And, 1995].
Dac, dimpotriv, cheia de cutare a nodului_tat scade, devenind mai mic dect
cheia de cutare a unui nod_u, atunci este sucient s schimbm ntre ele nodul_tat
cu nodul_u avnd cheia de cutare cea mai mare, apoi s continum procesul n mod
descendent, pn cnd proprietatea de ansamblu este restabilit. Vom spune c
valoarea modicat a fost cernut ctre noua sa poziie [And, 1995].
Metoda de sortare prin ansambluri, se bazeaz pe reprezentarea arborescent a
unei tabele date.
6.2.7.2 Descrierea algoritmului
a. Construirea ansamblului : Descrierea general a algoritmului n Pseudocod
este:
Specicarea problemei de construire a ansamblului , avnd ca date de in-
trare tabela A, dimensiunea maxim a tabelei N, este urmtoarea:
288 6. Tehnici de sortare
DATE A, N;
REZULTATE Ansamblu; { Ansamblul construit din tabela nesortat A }
Descrierea general a algoritmului de creare al ansamblului n Pseudocod este:
ALGORITMUL Creare_Ansamblu ESTE:
CITETE A, N; { Ansamblul construit din tabela nesortat A }
PENTRU i := (N div 2); 1 EXECUT
CHEAM Cernere (A, N, i);
SF-PENTRU
SFALGORITM
ALGORITMUL Cernere (B, M, j) ESTE:
k := j: { Se cerne valoarea din tabela B[j] }
REPET
l := k; { Gsete ul cu valoarea cea mai mare }
DAC (2l <= M) i (B[2l] > B[k]) ATUNCI
k := 2l;
SFDAC
DAC (2l < M) i (B[2l +1] > B[k]) ATUNCI
k := 2l +1;
SFDAC
temp := B[l];
B[l] := B[k];
B[k] := temp;
PNCND l = k SFREP
SFALGORITM
n Figura 6.8 avem un exemplu de construire a unui ansamblu. Nodurile
reprezentate cu cercuri duble semnic elementele care constituie ansamblul , iar
nodurile reprezentate cu cercuri colorate reprezint noduri care violeaz proprietatea
ansamblului .
Pasul 1: Construim arborele binar corespunztor tabelei originale
secvena de noduri este: 7, 5, 8, 2, 3, 9, 1, 6, 4;
arborele binar este reprezentat n Figura 6.8 (a)
6.2. Algoritmi de sortare 289
1 3 9 1
4 6
9
3 2
8 5
7
4 6
2
8 5
7
1 3
4 2
9 6
8 5
7
b) a) c)
1 8 1
4 2
8
3 5
9 6
7
4 2
3 6
9 5
7
1
3
4 2
7 5
8 6
9
f) ansamblu
e) d)
Figura 6.8: Construirea unui ansamblu A cu 9 elemente
Pozitia 1 2 3 4 5 6 7 8 9
tabela originala 7 5 8 2 3 9 1 6 4
dupa (b) 7 5 8 6 3 9 1 2 4
dupa (c) 7 5 9 6 3 8 1 2 4
dupa (d) 7 6 9 5 3 8 1 2 4
dupa (e) 9 6 8 5 3 7 1 2 4
290 6. Tehnici de sortare
Pasul 2: Nodul cu cheia 2 violeaz proprietatea de ansamblu (arborele binar
este reprezentat n Figura 6.8 (b))
cernem valoarea nodului cu cheia 2;
interschimbm nodul cu cheia 2 cu nodul cu cheia 6;
arborele binar este reprezentat n Figura 6.8 (c).
Pasul 3: Nodul cu cheia 8 violeaz proprietatea de ansamblu (arborele binar
este reprezentat n Figura 6.8 (c)).
cernem valoarea nodului cu cheia 8;
interschimbm nodul cu cheia 8 cu nodul cu cheia 9;
arborele binar este reprezentat n Figura 6.8 (d).
Pasul 4: Nodul cu cheia 5 violeaz proprietatea de ansamblu (arborele binar
este reprezentat n Figura 6.8 (d))
cernem valoarea nodului cu cheia 5;
interschimbm nodul cu cheia 5 cu nodul cu cheia 6;
arborele binar este reprezentat n Figura 6.8 (e).
Pasul 5: Nodul cu cheia 7 violeaz proprietatea de ansamblu (arborele binar
este reprezentat n Figura 6.8 (e))
cernem valoarea nodului cu cheia 7;
interschimbm nodul cu cheia 7 cu nodul cu cheia 9;
arborele binar este reprezentat n Figura 6.8 (f).
n Figura 6.8 (f) avem reprezentat ansamblul construit din tabela A.
Implementarea algoritmului de creare al ansamblului n limbajul Pascal este:
Procedure Creare_Ansamblu (var A: arraytype, rst, last: integer);
var
r, max: integer;
ok: boolean;
Begin
6.2. Algoritmi de sortare 291
r := rst; ok:=false;
While (r*2 <= last) and not ok do
Begin
If r*2 = last then
max :=r*2
Else
If A[r*2] > A[r*2+1] then
max := r*2
Else
max := r*2+1;
If A[r] < A[max] then
Begin
Swap( A[r], A[max] );
r := max;
End
Else
ok := true;
End
End;
b. Sortare cu ansambluri : Fiind dat o tabel nesortat A, de dimensiune N, s
presupunem c am construit ansamblul corespunztor tabelei A. Astfel, vom putea
accesa uor elementul maxim din tabel pentru c acesta este chiar nodul rdcin al
ansamblului i n reprezentarea cu ajutorul tabelei va nregistrarea A[1]. Aceast
nregistrare va interschimbat cu nregistrarea A[N]. Ne vom ocupa n continuare
de primele N1 nregistrri A[1], . . . , A[N-1], care alctuiesc aproape un ansamblu,
iari apelm la algoritmul de creare al ansamblului pentru aceste nregistrri, . . . .,
.a.m.d., pn cnd toate nregistrrile vor la locul potrivit, adic toate nregistrrile
vor sortate.
6.2.7.3 Implementarea algoritmului
Specicarea problemei de sortare, avnd ca date de intrare tabela A, dimensiunea
maxim a tabelei N, este urmtoarea:
DATE A, N;
REZULTATE A; { tabela A sortat n ordine cresctoare }
292 6. Tehnici de sortare
Descrierea general a algoritmului de sortare n Pseudocod este:
ALGORITMUL SORTARE_Ansambluri ESTE:
CITETE A, N;
CHEAM Creare_Ansambluri;
PENTRU i := N; 2 EXECUT
temp := A[l];
A[1] := A[i];
A[i] := temp;
CHEAM Cernere (B, i -1, 1);
SF-PENTRU
SFALGORITM
Algoritmul Sortare_Ansambluri construiete ansamblul original pentru ele-
mentele nesortate si sorteaz elementele n ansamblu prin schimbarea nodului rdcin
A[1], cu ultimul element nesortat A[i], apoi rearanjeaz elementele rmase.
Implementarea algoritmului de sortare prin ansambluri n limbajul Pascal este:
Procedure SORTARE_Ansambluri (var A: arraytype; N: integer);
Var i: integer;
Begin
Creare_Ansambluri (A, 1, N);
For i:= N downto 2 do {sortare}
Begin
Swap(A[1],A[i]);
Creare_Ansambluri (A,1,i-1);
End
End;
6.2.7.4 Complexitatea algoritmului
Un arbore binar complet cu N noduri are nevoie de log
2
(N +1) operaii, n cazul cel
mai nefavorabil, pentru a cerne nodul rdcin, astfel nct s ajung n poziia de nod
frunz. Algoritmul Creare_Ansamblu efectueaz un numr de log
2
N interschimbri,
deci complexitatea sa va O(log
2
N) [Tom, 1997].
Ciclul PENTRU din algoritmul de sortare se va executa de N-1 ori, deci complexi-
tatea algoritmului de sortare este O(N log
2
N).
6.2. Algoritmi de sortare 293
Algoritmul de sortare prin ansambluri are complexitatea O(N log
2
N) n toate
din cele trei cazuri de analizat: cazul general, favorabil i nefavorabil [Knu, 1976].
Pentru tabele mici algoritmul de sortare prin ansambluri este inecient, dar
foarte ecient pentru cele tabele mari. Nu necesit memorie suplimentar. E-
ciena algoritmul de sortare prin ansambluri nu este afectat de ordinea iniial a
elementelor.
6.2.8 Algoritmul de sortare RADIX
6.2.8.1 Descrierea general a metodei
Sortarea RADIX (sau sortarea digital) este o metod de sortare care precede apariia
calculatoarelor electronice, ind inspirat dintr-o metod de sortare mecanic a
cartelelor perforate. Este una din cele mai eciente metode de sortare intern, cu
condiia ca dimensiunea N a numrului de nregistrri de sortat s nu e prea mic,
iar cheile dup care se face ordonarea s nu e prea mici.
Algoritmul de sortare Radix trateaz cheile ca i cum ar numere reprezentate
ntr-o baz M, utiliznd cifrele din reprezentarea individuale a numerelor (de exemplu,
caracterele pot reprezentate n baza 128).
Dac folosim clasica reprezentare zecimal, deci M = 10, vom folosi 10 buzunare
corespunznd celor 10 cifre zecimale ale sistemului de numeraie zecimal. Fiecare
coloan este sortat ncepnd cu rangul cel mai puin semnicativ al cheilor (primul
din dreapta), mutnd nregistrrile din zona de intrare a algoritmului de sortare ntr-o
zon auxiliar a algoritmului de sortare. Procesul de sortare continu apoi cu urm-
torul rang semnicativ, pn cnd, n pasul nal se ordoneaz toate nregistrrile.
6.2.8.2 Descrierea algoritmului
Putem organiza nregistrrile de sortat n buzunare (pocket), ecare buzunar cores-
punznd unei cifre din reprezentarea cheilor de sortat n baza M. Fiecare buzunar
poate reprezentat ca o structur de date de tip coad (list FIFO). La sfritul
ecrui pas al procesului de sortare, cozile pot combinate uor n ordine potrivit.
Dac numrul maxim de cifre ntr-o cheie este M, atunci vor necesari M pai
de sortare, pornind de la cifra cea mai puin semnicativ la cifra cea mai semnica-
tiv. Este recomandat a se folosi reprezentarea nlnuit, sub forma de list simpl
nlnuit, a structurii de date corespunznd buzunarelor, deoarece nu putem ti cte
nregistrri vor intra ntr-un buzunar.
Prima dat, vom sorta nregistrrile dup cifra cea mai puin semnicativ a
cheii, interclasm apoi buzunarele. Repetm procesul de la primul pas, sortnd
294 6. Tehnici de sortare
nregistrrile dup cifra urmtoare, interclasm iari buzunarele, .a.m.d.
Exemplu. S considerm urmtoarea secven de numere de sortat n ordine cresc-
toare [Tre, 1986]:
42, 23, 74, 11, 65, 57, 94, 36, 99, 87, 70, 81, 61
Fiind vorba de o reprezentare zecimal vom avea nevoie de 10 buzunare pentru
procesul de sortare. Datorit ordinului de mrime al numerelor de sortat, avem doar
2 cifre de reprezentare, cifra unitilor i cifra zecilor.
Pasul 1: Prelucrm datele de sortat dup cifra unitilor n cele 10
buzunare
61
81 94 87
70 11 42 23 74 65 36 57 99
Buzunar: 0 1 2 3 4 5 6 7 8 9
Pasul 2: Interclasm buzunarele
obinem secvena de chei: 70, 11, 81, 61, 42, 23, 74, 94, 65, 36, 57, 87, 99
Pasul 3: Prelucrm datele de sortat dup cifra zecilor n cele 10 buzunare
65 74 87 99
11 23 36 42 57 61 70 81 94
Buzunar: 0 1 2 3 4 5 6 7 8 9
Pasul 4: Interclasm buzunarele
obinem secvena de chei: 11, 23, 36, 42, 57, 61, 65, 70, 74, 81, 87, 94, 99
6.2.8.3 Implementarea algoritmului
Specicarea problemei de sortare, avnd ca date de intrare tabela A, dimensiunea
maxim a tabelei N, este urmtoarea:
DATE A, N, M; { M reprezint baza sistemului de numeraie }
REZULTATE A; { tabela A sortat n ordine cresctoare }
Descrierea general a algoritmului de sortare n Pseudocod este:
6.2. Algoritmi de sortare 295
ALGORITMUL SORTARE_RADIX ESTE:
CITETE A, N, M;
k:= @numrul maxim de cifre necesar reprezentrii cheilor din tabela A;
PENTRU i := 1; k EXECUT
@golete buzunarul B[i];
PENTRU j := 1; N EXECUT
@analizeaz cifra i a cheii A[j] i introducem nregistrarea n
buzunarul B[i ];
SF-PENTRU
@ interclaseaz buzunarele B[1], B[2],. . . , B[M];
SF-PENTRU
SFALGORITM
Implementarea algoritmului de sortare prin ansambluri n limbajul Pascal este:
Fie dat o mulime de N nregistrri, organizat ca o list nlnuit cu cm-
purile cheie (key) i legtur (next). Vectorii head si tail conin adresele primelor
i res-pectiv ultimelor nregistrri din ecare buzunar (coad). Variabila i este in-
dexul pasului de sortare, variabila j este indexul buzunarelor, variabila r este variabila
pointer al nregistrrii curente. Variabila h de tip ntreg corespunde cifrei de analizat
din cheie, variabila M reprezint numrul maxim de cifre care alctuiesc cheia (key
= c
1
c
2
c
3
. . . c
M1
c
M
).
Function SORTARE_RADIX (r : list ) : list;
var head, tail : array[0..9] of list;
i, j, h : integer;
Begin
For i:=M downto 1 do {numrul de pai necesari}
Begin
For j:= 0 to 9 do
head[j] := nil; {iniializeaz listele corespunztoare buzunarelor}
While r <>nil do {pune nregistrrile n buzunarul corespunztor}
Begin
h := charac( i, r.key ); {obtine bitul i al cheii }
If head[h]= nil then
head[h] := r
Else
tail[h].next := r;
tail[h] := r;
296 6. Tehnici de sortare
r := r.next;
End;
r := nil; { interclasm buzunarele }
For j:=9 downto 0 do
If head[j] <> nil then
Begin
tail[j].next := r;
r := head[j]
End;
End;
SORTARE_RADIX := r;
End;
6.2.8.4 Complexitatea algoritmului
Pentru ca algoritmul de sortare RADIX s e performant este necesar s folosim
structuri de date potrivite De exemplu, este preferabil ca s avem nregistrrile de
sortat organizate ca o list simplu nlnuit i nu ca o tabel static. Dac folosim
organizarea sub form de list simpli nlnuit, atunci nu va trebui s copiem efectiv
nre-gistrrile din structura iniial n buzunare, ci doar s mutm adresa nregistrrii
dintr-o list n alta. De asemenea, pentru ca interclasarea s e rapid avem nevoie
de pointeri la sfritul ecrei liste.
Complexitatea algoritmului de sortare Radix este liniar, adic de complexitate
O(N), dac cheile de sortare sunt de tip ntreg sau de tip ir de caractere cu lungime
x [Tre, 1984].
Dac avem N nregistrri de sortat cu maximum M cifre necesare pentru
reprezentare, atunci complexitatea algoritmul de sortare RADIX este O(MN).
Bibliograe
[Ata] Atanasiu, A. , R. Pintea [1996]. Culegere de probleme Pascal, Editura
Petrion, Bucureti.
[Aho] Aho, A. V., J. E. Hopcroft, J. D. Ullman [1974]. The Design and Analysis
of Computer Algorithms, Addison-Wesley, Reading, Massachusetts.
[Aho] Aho, A. V., J. E. Hopcroft, J. D. Ullman [1987]. Data Structures and Algo-
rithms, Addison-Wesley, Reading, Massachusetts.
[Alb] Albeanu, G. [1994]. Programare n Pascal i Turbo Pascal. Culegere de prob-
leme, Editura Tehnic, Bucureti.
[And] Andonie, R., I. Grbacea [1995]. Algoritmi fundamentali. O perspectiv
C++, Editura Libris, Cluj-Napoca.
[Baa] Baase, S. [1987]. Computer Algorithms. Introduction to Design and Analysis,
Addison-Wesley, Reading, Massachusetts.
[Bla] Blaga P., G. Coman, S. Groze [1978]. Bazele Informaticii I. Culegere de
probleme, Litograa Universitii Babe-Bolyai, Cluj-Napoca.
[Bh] Bhm, C., T. C. Jacopini [1966]. "Flow Diagrams, Turing Machines and
Languages with only two Formation Rules", Comm. A.C.M. 9:5.
[Boi] Boian F., M. Freniu [1992]. Bazele Informaticii. Limbajul Pascal, ediia a
II-a, Litograa Universitii Babe-Bolyai, Cluj-Napoca.
[Bur] Burdescu, D.D. [1998]. Analiza complexitii algoritmilor, Editura Albastr,
Bucureti.
[Coo] Cook, S. A. [1970]. "The complexity of theorem-proving procedure", 3-rd
ACM Symposium of Computing, pg 151-158.
297
298 Bibliograe
[Cri] Cristea, V., I. Athanasiu, E. Kalisz, A. Pnoiu [1992]. Turbo Pascal 6.0,
Editura Teora, Bucureti.
[Cri] Cristea, V., I. Athanasiu, E. Kalisz, V. Iorga, [1993]. Tehnici de programare,
Editura Teora, Bucureti.
[Dal] Dale N., S. C. Lilly [1988]. Pascal Plus Data Structures, D. C. Heath and
Company, Lexington, Massachusetts.
[For] Fortune, S., C. J. Van Wyk [1993]. "Ecient Exact Arithmetic for Computa-
tional Geometry", Proceedings of the 9th ACM Symposium Computational
Geometry.
[Fre] Freniu M., S. Groze [1986]. Bazele Informaticii, ediia a II-a, Litograa
Universitii Babe-Bolyai, Cluj-Napoca.
[Giu] Giumale, C.A. [2004]. Introducere n analiza algoritmilor. Teorie i aplicaie,
Editura Polirom, Bucureti.
[Hor] Horowitz E., S. Sahni [1978]. Fundamentals of Computer Algorithms, Com-
puter Science Press, Rockville.
[Knut] Knuth D. E, [1976]. Tratat de programarea calculatoarelor. Algoritmi fun-
damentali, Editura Tehnic, Bucureti.
[Knu] Knuth, D. E. [1976]. Tratat de programare a calculatoarelor. Sortare i
cutare, Editura Tehnic, Bucureti.
[Kor] Korsh, J. F., L. J.Garrett [1988]. Data Structures, Algorithms and Program
Style Using C, PWS-Kent Publishing Co., Boston.
[Lev] Lewis, H.R., L. Denenberg [1991]. Data Structures & Their Algorithms,
Harper Collins Publishers, New-York.
[Liv] Livovschi L., [1980]. Scheme logice. Semnicaie, elaborare, vericare,
testare, Editura Tehnic, Bucureti.
[Liv] Livovschi L., H. Georgescu, [1986]. Sinteza i analiza algoritmilor, Editura
Stiinic i Enciclopedic, Bucureti.
[Moc] Mocanu, M., G. Marian, C. Bdic, [1993]. 333 probleme de programare,
Editura Teora, Bucureti.
[Sed] Sedgewitz, R. [1988]. Algorithms, Addison-Wesley, Reading, Massachusetts.
Bibliograe 299
[Sed] Sedgewitz, R. [1990]. Algorithms in C, Addison-Wesley, Reading, Mas-
sachusetts.
[She] Shewchuk, J. R. [1997]. "Floating-point arithmetic and fast robust geometric
predicates", Discrete and Computational Geometry, 18.
[Ski] Skiena, S. [1997]. The Algoritm Design Manual, Editura Springer-Verlag,
New-York.
[Tom] Tomescu, I., [1972]. Introducere n combinatoric, Editura Tehnic, Bu-
cureti.
[Tom] Tomescu, I. [1981]. Probleme de combinatoric i teoria grafurilor, Editura
Didactic i Pedagogic, Bucureti.
[Tom] Tomescu, I., [1997]. Data Structures, Editura Universitii din Bucureti,
Bucureti.
[Tre] Tremblay J. P., P. G. Sorenson [1984]. An Introduction to Data Structures
with Applications, second edition, McGraw-Hill, New-York.
[Tud] Tudor, S. [1993]. Tehnici de programare i structuri de date, vol. II, Editura
Turbo Rabbit, Bucureti.

S-ar putea să vă placă și