Escolar Documentos
Profissional Documentos
Cultura Documentos
Algoritmi si structuri de
date II
Note de laborator
Ioana Pomparau
Versiunea: 28.04.2015
Cuprins
Prefata i
4 Tablouri de dispersie 13
4.1 Tabele de dispersie . . . . . . . . . . . . . . . . . . . . . . . . 13
4.2 Tema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
8 Recapitulare 34
2
Prefata
i
Laboratorul 1
Programarea orientata pe
obiecte n limbajul C++
Mai jos sunt prezentate cateva aspecte n legatura cu diferentele ntre limba-
jele C si C++.
i n t main ( ) { i n t main ( ) {
char nume [ 1 5 ] ; char nume [ 1 5 ] ;
char prenume [ 1 5 ] ; char prenume [ 1 5 ] ;
int varsta ; int varsta ;
1
Exemplul 1.2. Transmiterea parametrilor prin referinta.
i n t main ( ) { i n t main ( ) {
int a , b ; int a , b ;
i n t main ( ) { i n t main ( ) {
i n t p=( i n t ) m a l l o c ( s i z e o f ( i n t ) ) ; i n t p = new i n t ;
p = 10 ; p = 10 ;
i n t v =( i n t ) m a l l o c ( 3 s i z e o f ( i n t ) ) ; i n t v = new i n t [ 3 ] ;
v[2] = 5; v[2] = 5;
free (p ); delete p;
free (v ); delete [] v ;
2
1.1 Programare orientata pe obiecte
Paradigma de programare orientata pe obiecte are la baza conceptul de
obiect. Obiectele descriu entitati, actiuni, obiecte, fenomene din viata reala.
Cu alte cuvinte, obiectele reprezinta structuri de date menite sa contina
informatii despre notiunea pe care o modeleaza.
Schema dupa care sunt create obiectele se numeste clasa. Clasele contin
caracteristicile (atributele) si actiunile (metodele) unui obiect. Acele atribute
si metode care pot fi accesate n afara clasei se vor declara cu specifica-
torul public. Crearea unui obiect dupa modelul clasei poarta denumirea de
instantiere.
In cadrul unei clase se pot defini doua tipuri speciale de metode: con-
structori si destructori. Astfel de metode nu au tip definit (nu sunt nici de
tip void) si sunt apelate implicit la crearea unui obiect (instantiere), respec-
tiv la distrugerea acestuia. Constructorul poarta numele clasei. Destructorul
are denumirea formata din simbolulsi denumirea clasei.
Mai jos este un exemplu n care se defineste o clasa menita sa modeleze
conceptul de figura geometrica de tip cerc. Caracteristicile unui obiect de tip
cerc sunt date centrul si raza sa. Acestea au fost declarate private pentru a
nu se putea accesa si modifica n afara clasei.
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
struct P o i n t {
float x ;
float y ;
};
class Circle {
private :
struct P o i n t c e n t e r ;
float radius ;
public :
C i r c l e ( struct P o i n t c e n t e r C o o r d , f l o a t r a d i u s V a l u e ) {
center = centerCoord ;
radius = radiusValue ;
}
float getArea ( ) {
return r a d i u s r a d i u s 3 . 1 4 ;
}
};
3
i n t main ( ) {
struct P o i n t C ;
float r ;
C i r c l e m y C i r c l e (C, r ) ;
cout<<" The circle has radius "<<m y C i r c l e . g e t R a d i u s ( )
<<" and area "<<m y C i r c l e . g e t A r e a ( ) ;
1.2 Tema
Exercitiul 1.1 . Descarcati fisierul Lab1 Circle.cpp si completati codul con-
form instructiunilor.
4
Laboratorul 2
5
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
struct Node{
i n t key ;
float info ;
Node n e x t ;
};
class SingleLinkedList {
private :
struct Node head ;
public :
S i n g l e L i n k e d L i s t ( i n t keyValue , f l o a t i n f o V a l u e = 0 ) {
head = new Node ;
head>key = keyValue ;
head>i n f o = i n f o V a l u e ;
head>n e x t = NULL;
}
SingleLinkedList (){
while ( head != NULL) {
Node temp = head>n e x t ;
d e l e t e head ;
head = temp ;
}
}
void a d d F i r s t ( i n t keyValue , f l o a t i n f o V a l u e = 0 ) {
Node temp = new Node ;
temp>key = keyValue ;
temp>i n f o = i n f o V a l u e ;
temp>n e x t = head ;
head = temp ;
}
temp>n e x t = newNode ;
}
void p r i n t ( ) {
cout<<" Current list : " ;
Node temp = head ;
while ( temp != NULL) {
cout<<temp>key<<" : "<<temp>i n f o <<" ; ";
temp = temp>n e x t ;
}
cout<<e n d l <<e n d l ;
6
}
};
i n t main ( ) {
/* Static memory allocation - the memory is freed at the end
of the block , in this case , of main ()
*/
S i n g l e L i n k e d L i s t myList ( 1 , 6 4 . 6 ) ;
myList . p r i n t ( ) ;
myList . a d d F i r s t ( 2 , 1 2 8 . 7 ) ;
myList . addLast ( 3 , 2 5 6 . 8 ) ;
myList . p r i n t ( ) ;
Intr-o lista dublu nlantuita, fiecare element retine atat adresa urmatorului
nod, cat si a precedentului.
7
2.1 Tema
Exercitiul 2.1. Descarcati fisierul Lab2 SingleLinkedList.cpp si completati
codul conform instructiunilor.
Exercitiul 2.4
. Descarcati fisierul Lab2 CardsGame.cpp si completati codul
conform instructiunilor.
8
Laboratorul 3
9
Prin container ntelegem clase care gestioneaza structuri de date precum
vectori, liste, stive, cozi etc. Acestea ar trebui sa poata stoca orice tip de
data. Din acest motiv utilizeaza sabloane (templates). Mai jos este prezentat
un exemplu de utilizare al clasei stack.
#i n c l u d e <i o s t r e a m >
#i n c l u d e <s t a c k >
u s i n g namespace s t d ;
i n t main ( )
{
s t a c k <int> myStack ;
int i ;
u s i n g namespace s t d ;
i n t main ( )
{
v e c t o r <int> myVector ;
int i ;
f o r ( i = 0 ; i < 1 0 ; i ++) myVector . p u s h b a c k ( i i ) ;
v e c t o r <int > : : i t e r a t o r i t ;
f o r ( i t = myVector . b e g i n ( ) ; i t != myVector . end ( ) ; i t ++)
cout <<i t <<" " ;
cout<<e n d l ;
10
Sunt implementati algoritmi clasici sub forma unor functii care prelu-
creaza datele memorate n containere. Modificand codul de mai sus, ele-
mentele vectorului sunt inversate nainte de a fi afisate.
#i n c l u d e <i o s t r e a m >
#i n c l u d e <v e c t o r >
#i n c l u d e <a l g o r i t h m >
u s i n g namespace s t d ;
i n t main ( )
{
v e c t o r <int> myVector ;
int i ;
f o r ( i = 0 ; i < 1 0 ; i ++) myVector . p u s h b a c k ( i i ) ;
v e c t o r <int > : : i t e r a t o r i t ;
f o r ( i t = myVector . b e g i n ( ) ; i t != myVector . end ( ) ; i t ++)
cout <<i t <<" " ;
cout<<e n d l ;
3.3 Tema
Exercitiul 3.1 . Descarcati fisierele Lab5 Stack.cpp si Lab5 Queue.cpp si
completati codul conform instructiunilor.
11
Exemplu de labirint pentru n = 4
1 0 0 1
0 1 1 2
0 0 1 0
0 0 0 0
12
Laboratorul 4
Tablouri de dispersie
13
Apare atunci ntrebarea: putem construi un vector n care cheia
unui element sa ne dea pozitia acestuia? Daca acest lucru ar fi real-
izat, atunci cautarea unui element ar presupune calcularea indexului sau si
verificarea existentei n vector pe pozitia obtinuta. In acest caz si cautarea
ar avea complexitate constanta.
O idee initiala ar fi sa se construiasca un vector ai carui indecsi sa fie chiar
posibilele chei ale elementelor (adresare directa). Aceasta abordare nu este
nsa practica ntotdeauna, deoarece universul cheilor ar putea fi mult prea
mare relativ la memoria care poate fi folosita.
Pentru a evita astfel de situatii se folosesc tabele de dispersie. Acestea
reprezinta structuri de date care implementeaza tablouri asociative: cheii
unui element i se asociaza un cod din plaja de valori ale indecsilor unui
vector; insertia si cautarea se vor face la pozitia data de acest cod.
Maparea ntre cheile valorilor de memorat si universul de chei ale struc-
turii de date folosite se realizeaza cu ajutorul unor functii numite functii de
dispersie (vezi http://en.wikipedia.org/wiki/Hash_function). Aceste
functii transforma valori de dimensiuni variabile n coduri de dimensiune
fixata ce pot fi apoi folosite cu rol de indecsi, realizand practic o criptare
ntr-un singur sens.
Cum n general universul cheilor este mult mai mare decat multimea de
indecsi ai tabloului de dispersie, o functie de dispersie va asocia mai multor
chei acelasi cod. Acest fenomen poarta numele de coliziune. O posibila
rezolvare a acestei probleme se face prin nlantuire: la fiecare pozitie a
tabelului se memoreaza o legatura catre o lista nlantuita de elemente. Atunci
un element va fi inserat sau cautat n lista corespunzatoare codului hash al
acestuia.
Eficienta acestei abordari depinde de cat de buna este o functie de
dispersie. Aceasta trebuie sa aiba urmatoarele proprietati: sa fie usor de
calculat, sa evite coliziunile si sa distribuie uniform cheile n tabel.
Daca aceste conditii sunt respectate, atunci operatia de insertie are com-
plexitate O(1), iar cea de cautare are complexitate medie O(n/m), unde n
reprezinta numarul de elemente memorate n tabel, iar m reprezinta numarul
de pozitii ale acestuia.
14
O aplicatie a functiilor de dispersie apare n autentificarea utilizatorilor.
Pentru a asigura o buna securitate a parolelor, acestea nu sunt memorate
n clar. Unei parole i se aplica o serie de functii de dispersie si ceea ce se
memoreaza n baza de date este valoarea obtinuta. Atunci cand un utilizator
introduce o parola pentru a se autentifica, acesteia i se aplica aceeasi serie
de functii si rezultatul se compara cu valoarea memorata pentru respectivul
utilizator. Daca sunt egale se considera ca autentificarea a fost realizata
cu succes. Important n aceasta situatie este ca fiind dat un cod hash si
cunoscandu-se functia cu care a fost obtinut sa fie dificil de calculat valoarea
initiala.
Tabele de dispersie sunt folosite n implementarea tablourilor asociative,
a unei memorii de tip cache etc.
4.2 Tema
Exercitiul 4.1. 1. h(x) = x mod 32;
2. h(x) = x mod 31;
M 2
3. h(x) = W (x mod W ) , unde W = 26 si M = 25 ;
M
4. h(x) = W (ax mod W ) , unde W = 26 , M = 25 si a = 101;
5. h(x) = [m (Ax mod 1)], unde prin (Ax mod
1) se noteaza partea
( 51)
fractionara a lui Ax, iar m = 1000 si A = 2
.
calculati numarul de valori posibile generate (reprezentand indecsii unor
tabele de dispersie).
Exercitiul 4.2 . Generati aleator 1000 de numere ntregi cu valori cuprinse
ntre 0 si 9999. Aplicati functiile de dispersie de la exercitiul anterior acestor
valori si, fara a construi efectiv un tabel de dispersie, pentru fiecare functie
1. numarati coliziunile de pe fiecare cheie;
2. calculati urmatoarea suma
m1 n 2
X ci m
n ,
i=0 m
15
Exercitiul 4.3. Scrieti o clasa care implementeaza un tabel de dispersie.
Se va utiliza functia de dispersie de la 1. Coliziunile vor fi rezolvate prin
nlantuire. Realizati si un exemplu de utilizare al clasei.
16
Laboratorul 5
17
5.1 Parcurgeri ale arborilor binari
Parcurgerile specifice arborilor binari sunt n latime (breadth-first) si n
adancime (recursive, depth-first): preordine (RSD), inordine (SRD) si
postordine (SDR).
18
2. cheie(x) < cheie(z), oricare ar fi z un nod din subarborele drept al
nodului x.
19
5.2.2 Operatii specifice
Inserarea unui nou nod. Se procedeaza ntr-un mod asemanator operatiei
de cautare: se porneste de la radacina si prin comparatii succesive se merge
pe ramura din stanga sau din dreapta, daca nodul de inserat are cheia mai
mica sau egala decat a nodului curent, respectiv mai mare; cand se ajunge
la un subarbore vid se face insertia la acea locatie. Prin aceasta metoda se
pastreaza structura de arbore binar de cautare.
Exemplul 5.1. Sa presupunem ca dorim sa adaugam noduri cu cheile J,
respectiv A n arborele din figura de mai jos. Nodul cu cheia J se va insera
ca fiu drept al nodului de cheie I, iar cel cu cheia A se va insera ca fiu stang
al nodului deja existent de cheie A.
20
Stergerea unui nod. Daca nodul de sters este o frunza se poate elimina
direct din arbore, fara a-i fi afectata structura de arbore binar de cautare.
In caz contrar, pana cand nodul de sters devine frunza se fac interschimbari
ale acestuia cu nodul de cheie minima din subarborele drept sau de cheie
maxima din subarborele stang. Acest procedeu asigura mentinerea structurii
de arbore binar de cautare (de ce?).
5.3 Tema
Exercitiul 5.1. Sa se scrie parcurgerile n preordine, inordine si postordine
pentru fiecare din arborii de mai jos.
21
Exercitiul 5.2. Sa se insereze ntr-un arbore binar de cautare, initial vid,
urmatoarele chei, n ordinea data: 20, 5, 40, 1, 23, 15, 7, 6, 9, 0, 33, 20, 3,
10, 5, 6, 26, 4, 41.
Sa se stearga nodul cu cheia 10.
22
Laboratorul 6
RN1 orice subarbore vid al unui nod este tratat ca un nod frunza nil;
RN3 daca un nod este rosu atunci ambii fii sunt negri;
23
Pentru a justifica afirmatia de mai sus este suficient sa consideram pro-
prietatea RN4 si sa notam cu b numarul de noduri negre continute de orice
drum de la radacina la o frunza. Atunci orice astfel de drum are cel putin b
noduri negre si, conform proprietatii RN3 cel mult b noduri negre si b noduri
rosii.
Nodurile cu chei se mai numesc si noduri interne, iar frunzele (nodurile
nil) se numesc noduri externe.
Lema 6.1. Un arbore rosu - negru cu n noduri interne are naltimea cel mult
egala cu 2 log2 (n + 1).
24
Sunt folosite doua tipuri de rotatii: la stanga si la dreapta. Acestea sunt
descrise n imaginea de mai jos:
Introducem n continuare urmatoarea terminologie: se numeste Bunic
acel nod cu proprietatea ca este parintele parintelui nodului curent; se numeste
Unchi acel nod cu proprietatea ca are acelasi parinte ca si parintele nodului
curent.
Algoritm de insertie
- se coloreaza nodul de inserat cu rosu;
- se insereaza nodul procedand ca la arbori binari de cautare; nodul
inserat devine nod Curent;
- se efectueaza urmatorii pasi cat timp arborele nu este rosu negru
[1] daca nodul Curent este radacina se coloreaza cu negru;
[2] daca si Parintele si Unchiul sunt rosii, atunci amandoi pot fi
colorati cu negru iar Bunicul este colorat cu rosu; nodul Curent este
acum Bunicul si se reia de la pasul [1];
[3] daca Parintele este rosu, Unchiul este negru, nodul Curent este
fiu drept (stang) si Parintele este fiu stang (drept) se executa o rotatie la
stanga (dreapta) a Parintelui; se continua cu urmatorul pas cu Parintele
ca nod Curent;
[4] daca Parintele este rosu, Unchiul este negru si atat nodul Curent
cat si Parintele sunt fii stangi (drepti), atunci culorile Parintelui si ale
Bunicului sunt interschimbate si se executa o rotatie la dreapta (stanga)
a Bunicului.
6.3 Tema
Exercitiul 6.1. Fiind dat urmatorul arbore rosu - negru sa se adauge noduri
cu cheile 4, 9, 20, 6, 3 si 12.
25
Exercitiul 6.2 . Pornind de la clasa care implementeaza un arbore binar de
cautare, scrieti o clasa noua care modeleaza o structura de date de tip arbore
rosu - negru.
26
Laboratorul 7
7.1 B-arbori
Structurile de date de tip B-arbore generalizeaza notiunea de arbore binar de
cautare, asigurand totodata complexitatea logaritmica a operatiei de cautare.
Pentru un m numar natural nenul fixat arbitrar, spunem ca un arbore
m-ar (cu proprietatea ca orice nod are cel mult m fii) este b-arbore daca au
loc urmatoarele:
1. pentru fiecare nod, daca t este numarul de fii, atunci nodul are t 1
chei;
3. fiul cel mai din stanga al unui nod are toate cheile mai mici decat prima
cheie a parintelui; fiul aflat ntre doua chei k1 si k2 are cheile cu valori
cuprinse n intervalul [k1 , k2 ]; fiul cel mai din dreapta are cheile mai
mari decat ultima cheie a parintelui;
27
7.1.1 Operatia de cautare
Se realizeaza analog celei de la arbore binar de cautare. Se porneste de la
radacina si la fiecare pas se compara cheia cautata cu cheile nodului curent.
Cat timp nu s-a gasit sau nodul curent nu este frunza, daca nodul curent se
cauta n nodul curent doua chei de pe pozitii consecutive cu proprietatea ca
intervalul determinat de acestea doua contine cheia cautata. Se continua cu
nodul cuprins ntre aceste chei.
28
Inserand cheia H n nodul radacina se depaseste numarul admis de chei.
Cheia mediana se muta ntr-un nod nou care devine radacina si nodul curent
(care este n particular si frunza si radacina) se divide n doua noduri:
29
In urma efectuarii tuturor inserarilor arborele final rezultat este urmatorul:
30
7.2 Coduri Huffman
Codurile Huffman reprezinta o modalitate optima de arhivare a unui text
dat. Ideea de baza este ca fiecare caracter va fi nlocuit cu un cod format
din biti de 0 si 1 astfel ncat un caracter cu frecventa mare de aparitie sa
aiba un cod cat mai mic posibil fata de unul cu frecventa mica. Codurile
asociate sunt coduri cu prefix (nici un cod valid nu reprezinta prefixul unui
alt cod valid). In codarea Huffman textul dat este analizat pentru a se calcula
frecventa de aparitie a fiecarui caracter. Se construieste apoi un arbore binar
format din noduri frunze (asociate caracterelor) si noduri interne, astfel: se
porneste cu n noduri libere (frunze), unde n reprezinta numarul de caractere
distincte din text; fiecare nod contine un caracter si frecventa sa de aparitie;
se creeaza apoi un nod nou avand ca fii 2 noduri cu frecventa minima de
aparitie; se continua analog cu multimea de noduri din care s-au eliminat
cele doua noduri folosite si la care s-a adaugat noul nod creat; procesul se
ncheie atunci cand se ramane cu un singur nod, acesta devenind si radacina
unui arbore binar Huffman. Codul unui caracter se calculeaza parcurgand
lantul de la radacina la nodul frunza care l contine si considerand 0 daca
se merge pe directia fiului stang, respectiv 1 pentru fiul drept. Pentru a se
dezarhiva un text codat Huffman trebuie sa se cunoasca codurile caracterelor
(date de arborele Huffman).
31
32
7.3 Tema
Exercitiul 7.1
. Scrieti o clasa care modeleaza un B-arbore.
Exercitiul 7.2. Fisierul date.in contine un text format numai din literele
mici ale alfabetului latin.
4. Arhivati textul.
33
Laboratorul 8
Recapitulare
34