Sunteți pe pagina 1din 14

Ministerul Educaiei al Republicii Moldova

Universitatea Tehnic a Moldovei

Departametul Ingineria software i automatic

RAPORT
Lucrarea de laborator nr. 4-5
la Structuri de date i algoritmi

A efectuat:
st. gr. AI-161 V.Platon

A verificat:
dr., conf.univ. M. Kulev

Chiinu -2017
Lucrarea de laborator nr. 4-5
Tema: Implementarea tipului de date abstract Arbore binar geniralizat in
limbajul C. Algoritmi iterativi si algoritmi recursivi.

Scopul lucrrii: Obinerea deprinderilor de implementare practice in limbajul C a


tipului de date abstract (TDA) Arbore binar geniralizat utiliznd algoritmi
iterativi si recursivi.

Sarcina de lucru: De scris trei fiiere-text n limbajul C pentru implementarea si


utilizarea TDA Arbore binar geniralizat :
1. Fiierul antet arbore.h care conine: a) specificaia structurei nodului al
arborelui binar (conform variantei din lucrarea de laborator nr.1) i b) prototipurile
funciilor care asigur operaiunile de prelucrare a arborelui binar geniralizat.
Pentru lucrarea de laborator nr.4 n acest fiier trebuie de adaugat specificaiile
structurilor elementelor cozei i stivei unde vor fi stocate adresele nodurilor ale
arborelui binar, precum i prototipurile funciilor de inserare i eliminare a
elimentului pentru coada i stiva.
2. Fisierul arbore.cpp sau arbore.c care conine codurile (implementrile) tuturor
funciilor declarate n fiierul antet.
3. Fiierul utilizatorului lab4_5.cpp sau lab4-5.c care reprezint programul cu
funcia main( ) pentru prelucrarea arborelui binar geniralizat cu afiarea meniului
de optiuni pe ecran, si anume: crearea arborelui binar geniralizat n memoria
dinamic mpreun cu introducerea informaiei nodurilor arborelui de la tastatur
n regim interactiv, afiarea informatiei despre nodurile arborelui pe ecran (precum
i afiarea adreselor nodului current, copilului stng i copilului drept al acestora),
cutarea nodului dup unui cmp informaional al nodului, determinarea numrului
de noduri n arbore, determinarea nalimei a arborelui, eliberarea memoriei
dinamice alocate pentru arbore, ieire din program.

n lucrarea de laborator nr.4 funciile de prelucrare ale arborelui binar trebuie


implementate folosind algoritmi iterativi n 2 versiuni:
a) utiliznd coada - pentru parcurgerea arborelui n largime (parcurgerea arborelui
pe niveluri) i
b) utiliznd stiva pentru parcurgerea arborelui n adncime (parcurgerea
inordine: rdcin -> subarbore stng(drept) -> subarbore drept(stng). O excepie
face funcia de eliberare a memoriei dinamice alocate pentru arbore ( trebuie
folosit parcurgerea postordine: subarbore stng(drept) -> subarbore drept(stng) ->
rdcin).
n lucrarea de laborator nr.5 funciile de prelucrare ale arborelui binar trebuie
implementate folosind algoritmi recursivi pentru parcurgerea arborelui n
adncime: rdcin -> subarbore stng(drept) -> subarbore drept(stng). i aici o
excepie face funcia de eliberare a memoriei dinamice alocate pentru arbore
(trebuie folosit parcurgerea postordine: subarbore stng(drept) -> subarbore
drept(stng) -> rdcin).
n lucrarea de laborator nr.5 funcia de afiare a informaei despre nodurile
arborelui pe ecran, precum i a adreselor nodului current, copilului sting i
copilului drept al acestora, trebuie impementat pentru toate parcurgerile recursive
posibile ale arborelui binar.

Mersul lucrrii:
Noiuni principale din teorie i metode folosite:
Stiva
O stiv este o structur de date ale crei elemente sunt considerate a fi puse unul peste altul,
astfel nct orice element adugat se pune n vrful stivei, iar extragerea unui element se poate
face numai din vrful acesteia, n ordinea invers celei n care elementele au fost introduse.

Principiu de lucrarea stivei este LIFO( Last in First Out) ce inseamna ultimul a intrat,
primul a iesit. Deseori stiva este comparata cu gramada de placi. Pentru a lua placa a doua din
sus, trebuie mai intii de luat prima placa.

Exemplul de implimentarea in C
struct stack
{
nod *adrnod;
struct stack *prev;
};
Operaii cu stive
Creare
Pentru a crea o stiva vid se inializeaz vrful stivei cu 1 (vrful stivei indic ntotdeauna
poziia ultimului element, acestea fiind memorate ncepnd cu poziia 0).

Inserare (Push)
Pentru a insera un element e n vrful stivei S (operaia push) este necesar, n primul rnd,
verificarea stivei pentru a stabili dac este sau nu plin. Dac acest lucru este ndeplinit, se
memoreaz elementul i se incrementeaz dimensiunea; n caz contrar sarcina nu se poate
ndeplini.

int push(nod* v)
{
els *c;
c = (els*)malloc(sizeof(els));
if (c == NULL) return 0;
c->prev = top;
top = c;
c->adrnod = v;
return 1;
}

Extragere (Pop)
Pentru a extrage un element din vrful stivei (operaia pop) trebuie ca stiva s nu fie vid. Dac
nu este, atunci se reine valoarea din vrful stivei ntr-o variabil e i se decrementeaz vrful.

nod* pop()
{
els *c;
nod* v;

c = top;
v = c->adrnod;
top = c->prev;
free(c);
return v;
}
Vizitare
Accesarea/vizitarea elementului de la vrf stivei presupune determinarea valorii acestuia, valoare
care se va reine ntr-o variabil e, fr a o extrage.
Se poate observa c ultimele trei operaii au complexitatea O(1), iar prima operaie
complexitatea O(n).

Utilizarea
n informatic stiva joac un rol fundamental. Pentru a ntelege mecanisme fundamentale ale
programrii (de exemplu, functiile sau recursivitatea) este necesar cunoasterea notiunii de stiv.
Pe scurt, stiva este util n situatii n careeste necesar memorarea unor informatii si regsirea
acestora ntr-o ordinea anumit.

Coada
Coada este o structur de date in care accesarea se face dupa model FIFO (First In First Out).
Inserarea elementelor este posibila doar la sfirsitul coadei, iar extragerea numaai de la inceputul.

Coada poate fi comparata cu rindul in magazin.

Exemplul de implimentarea in C
typedef struct elq{
nod *adrnod;
struct elq *next;
}elq;

Totoadta cozile pot fi implementate si cu ajutorul multimii.


Operaii cu cozi
Singurele operatii ce pot fi executate cu o coad sunt:

crearea unei cozi vide;


inserarea unui element n coad;
extragerea unui element din coad;
accesarea unui element.
Utilizarea cozilor
Coada in programare se utilizea la fel ca n viaa real, atunci cnd avei nevoie pentru a efectua
anumite aciuni, n ordinea primirii lor. Un exemplu este organizarea de evenimente n Windows.
Atunci cnd utilizatorul exercit o aciune asupra cererii, cererea nu apeleaz procedura adecvat
(deoarece n acest moment aplicaia poate efectua alte aciuni), i el este trimis un mesaj care
conine informaii cu privire la ndeplinirea aciunilor, mesajul este trimis in coada de ateptare,
i numai atunci cnd mesajele primite anterior sunt procesate, aplicaia va face msurile
necesare.

Arbore binar. Notiune de arbore.


Un arbore binar este un arbore orientat in care fiecare varf are cel mult doi descendenti,
facandu-se insa distinctie clara intre descendentul drept si descendentul stang al fiecarui varf. Se
accepta si arborele binar cu 0 varfuri.

Arborii binari nu reprezinta cazuri particulare de arbori orientati, decat daca se face abstractie de
distinctia mentionata intre descendentul drept si cel stang al fiecarui varf. Intr-adevar daca un
varf are un singur descendent, aceasta informatie este suficienta in cazul unui arbore, dar
insuficienta in cazul unui arbore binar, cand trebuie precizat daca acest descendent este
descendent stang sau descendent drept.

Un arbore este compus din elementele numite noduri sau varfuri si legaturile dintre acestea.
Un nod situat pe un anumit nivel este nod tata pentru nodurile legate de el, situate pe nivelul
urmator, acestea reprezentand fiii sai. Fiecare nod are un singur tata, cu exceptia radacinii care
nu are tata. Nodurile fara fii se numesc noduri terminale sau frunze. Termenii ' nod tata', 'fiu' sau
'frate' sunt preluati de la arborii genealogici, cu care arborii se aseamana foarte mult.
Implementarea arborilor binari
typedef struct nod
{
Int info;
struct nod *left;
struct nod *right;
}nod;

Operatiile posibile cu arbori sunt la fel ca in cazul listelor:


traversarea arborelui ;
inserarea unui nod ;
cautarea unui nod ;
stergerea unui nod ;

Traversarea arborelui binar consta in parcurgerea pe rand a nodurilor in vederea prelucrarii


informatiilor atasate acestora. Traversarea arborelui presupune vizitarea fiecarui nod o singura
data, operatie echivalenta cu o liniarizare a arborelui.
Clasificare arborelor binare
a) Dupa structura
1. arbore binar oricare
2. arbore plin (strict)
3. arbore complet
4. arbore prefect
5. arbore degenerat
b) Dupa valorii stocare in nodul
1. Arbore simplu
2. Arbore binar de cautare
c) Dupa structura si valori
1. Heap

Metode de parcurgerea arborelor

A) Arborii binari pot fi parcursi prin metode specifice grafurilor: in adancime, latime.

B) Metode specifice arborilor binari :


Parcurgerea in inordine (stanga varf dreapta SVD) se parcurge mai intai subarborele
stang, apoi varful, apoi subarborele drept.
Parcurgerea in preordine (varf- stanga dreapta VSD) se parcurge mai intai varful,
apoi subarborele stang, apoi subarborele drept.
Parcurgerea in postordine (stanga dreapta varf SDV) se parcurge mai intai
subarborele stang, apoi subarborele drept si la sfarsit varful.
Listingul programului:
1) Fisierul antet cinema.h
typedef struct nod int show_queue();
{ nod* search_queue(char *fname);
char name[50]; int size_queue();
char adress[50]; int freemem_queue();
int num_tel;
int num_seats; int create_stack();
char boss[50]; int show_stack();
nod* search_stack(char *fname);
struct nod int size_stack();
*left; int freemem_stack();
struct nod
*right;
}nod; int read_file(char *fname);
int write_file(char *fname);
nod *root = NULL; int write_file2(char
*file_name);
typedef struct elq{
nod *adrnod; int inq(nod *v);
struct elq *next; nod* delq();
}elq; int push(nod *v);
nod* pop();
elq *first = NULL;
elq *last = NULL; int create_queue();
int show_queue();
typedef struct els{ nod* search_queue(char *fname);
nod *adrnod; int size_queue();
struct els *prev; int freemem_queue();
}els;
int create_stack();
els *top = NULL; int show_stack();
nod* search_stack(char *fname);
int inq(nod *v); int size_stack();
nod* delq(); int freemem_stack();
int push(nod *v);
nod* pop(); int read_file(char *fname);
int write_file(char *file_name);
int create_queue();
2) Fisierul cinema.c
#include <stdio.h> create_queue();
#include <conio.h> break;
#include <stdlib.h>
#include <string.h> case 2:
#include "cinema.c" system("cls");
create_stack();
break;
int main() case 3:
{ system("cls");
printf("De creat
int menu_1 = 1; radacina ? (1/0): ");
int menu_2 = 0; int f;
int menu_3 = 0; scanf("%d", &f);
int menu_4 = 0; if (f) {root =
char fname[20]; create_RSD();}
break;
while (1) case 4: menu_1 = 1; break;
{
while (menu_1) default:
{ printf("Error: Acesta
menu_1 = 0; optiune nu exista !");
system("cls"); getch();
printf("\tMENU \n\n"); menu_1 = 1;
puts("1. Introducerea datelor break;
de la tastatura");
puts("2. Citirea datelor din }
fisier"); break;
puts("");
puts("0. Iesire"); case 2:

printf("\nOptiunea: "); printf("Introdu numele


int optiune; fisierului \n");
fflush(stdin); fflush(stdin);
scanf("%d", &optiune); scanf("%s", &fname);
read_file(fname);
switch (optiune) break;
{
case 0: exit(0); break; default:
case 1: printf("Error. Acesta optiune nu
eticheta1 : exista !");
system("cls"); getch();
printf("Crearea arborelui cu menu_1 = 1;
ajutorul:\n\n"); break;
puts("1. Coada"); }
puts("2. Stiva"); }
puts("3. Recursie");
puts("");
puts("4. Inapoi"); system("cls"); fflush(stdin);
puts("0. Iesire"); printf("Alegeti modul de lucru
puts(""); :\n\n");
printf("Optiune: "); printf("1. Coada\n");
scanf("%d", &optiune); printf("2. Stiva\n");
switch (optiune) printf("3. Recursie\n");
{ printf("4. Salveaza in
case 0: exit(0); break; fisier\n");
case 1: puts("");
system("cls"); printf("5. Inapoi\n");
printf("0. Iesire\n\n"); printf("Coada nu este
printf("Optiune: "); formata !");
int optiune; getch(); break;}
fflush(stdin); char nume_coada[100];
scanf("%d", &optiune); printf("Dati numele
system("cls"); cinematografului pentru cautare:
");
switch(optiune) fflush(stdin);
{
case 0: exit(0); break; strupr(gets(nume_coada));
case 1: menu_2 = 1; break;
case 2: menu_3 = 1; break; nod *t;
case 3: menu_4 = 1; break; t =
case 4: search_queue(nume_coada);
printf("Introdu numele printf("\nCinematograf
fisierului cu extensia .txt\n"); cautat : \n\n");
scanf("%s",&fname); if (t)
write_file(fname); {
break; printf("Denumirea:
case 5: goto eticheta1; break; \"%s\"\n", strupr(t->name));
default: printf("Adresa: %s\n",
printf("Error: Acesta optiune nu strupr(t->adress));
exista !"); printf("Numarul de
getch(); telefon: %d\n", t->num_tel);
break; printf("Numar de locuri:
} %d\n", t->num_seats);
while (menu_2) printf("Director: %s
{ \n", t->boss);
system("cls"); fflush(stdin); printf("\n\n");
printf("Operatii - } else
Coada!\n\n"); printf("Cinematograf nu a fost
printf("1. Afisare\n"); gasit");
printf("2. Cautare\n"); getch();
printf("3. Marimea break;
arborelui\n");
printf("4. Eliberarea case 3:
memoriei\n"); if (root == NULL) {
puts(""); printf("Coada nu este
printf("5. Inapoi\n"); formata !");
printf("0. Iesire\n\n"); getch(); break;}
printf("Optiune: "); int x;
scanf("%d",&optiune); x = size_queue();
system("cls"); printf("Arborele are %d
switch(optiune) noduri.", x);
{ getch();
case 0: exit(0); break; break;
case 1:
if (root == NULL) { case 4:
printf("Coada nu este if (root == NULL) {
formata !"); printf("Coada nu este
getch(); break;} formata ! ");
show_queue(); getch(); break;}
getch(); int z;
break; z = freemem_queue();
if (z == 1)
case 2: printf("Eliberarea
if (root == NULL) { memoriei sa efecutat cu succes
!");
getch(); tt =
break; search_stack(nume_stack);
printf("\nCinematograf
case 5: cautat : \n\n");
menu_2 = 0; if (tt)
break; {
printf("Denumirea:
default: \"%s\"\n", strupr(tt->name));
printf("Error: Acesta printf("Adresa: %s\n",
optiune nu exista !"); strupr(tt->adress));
getch(); printf("Telefon: %d \n",
break; tt->num_tel);
} printf("Locuri: %d\n",
} strupr(tt->num_seats));
printf("Director: %s\n",
while (menu_3) tt->boss);
{ printf("\n\n");
system("cls"); fflush(stdin); } else
printf("Operatii - {
Stiva!\n\n"); printf("Acest
printf("1. Afisare\n"); cinematograf nu a fost gasit");
printf("2. Cautare\n"); }
printf("3. Marimea
arborelui\n"); getch();
printf("4. Eliberarea break;
memoriei\n");
puts(""); case 3:
printf("5. Inapoi\n"); if (root == NULL) {
printf("0. Iesire\n\n"); printf("Stiva nu
printf("Optiune: "); este formata ! ");
scanf("%d",&optiune); getch();
system("cls"); break;}
switch(optiune) int xx;
{ xx = size_stack();
case 0: exit(0); break; printf("Arborele are %d
case 1: noduri.", xx);
if (root == NULL) { getch();
printf("Stiva nu este break;
formata ! ");
getch(); break;} case 4:
show_stack(); if (root == NULL) {
getch(); printf("Stiva nu
break; este formata ! ");
getch(); break;}
case 2: int zz;
if (root == NULL) { zz = freemem_stack();
printf("Stiva nu if (zz == 1)
este formata ! "); printf("Eliberarea
getch(); break;} memoriei sa efecutat cu succes
char nume_stack[100]; !");
printf("Dati numele de getch();
cautare: "); break;
fflush(stdin);
case 5:
strupr(gets(nume_stack)); menu_3 = 0;
break;
nod *tt;
default:
printf("Error: Acesta printf("Numarul de
optiune nu exista !"); telefon: %d\n", ttt->num_tel);
getch(); printf("Numar de locuri:
break; %d\n", strupr(ttt->num_seats));
} printf("Director: %s
} \n", ttt->boss);
printf("\n\n");
while (menu_4) } else
{ printf("Cinematograf cu acesta
system("cls"); fflush(stdin); denumire nu exista");
printf("Operatii - getch();
Recursie!\n\n"); break;
printf("1. Afisare\n");
printf("2. Cautare\n"); case 3:
printf("3. Marimea if (root == NULL)
arborelui\n"); { printf("Recursia
printf("4. Eliberarea nu este formata ! ");
memoriei\n"); getch();
puts(""); break;}
printf("5. Inapoi\n"); static int n;
printf("0. Iesire\n\n"); n = sizeRSD(root);
printf("Optiune: "); printf("Arborele are %d
scanf("%d",&optiune); noduri.", n);
system("cls"); getch();
switch(optiune) break;
{
case 0: exit(0); break; case 4:
case 1: if (root == NULL) {
if (root == NULL) { printf("Recursia
printf("Recursia nu este formata ! ");
nu este formata ! "); getch(); break;}
getch(); break;} int zzz;
showRSD(root); zzz =
getch(); freememSDA(root);
break; if (zzz == 1)
case 2: printf("Eliberarea
if (root == NULL) { memoriei sa efecutat cu succes
printf("Recursia !");
nu este formata ! "); getch();
getch(); break;} break;
char nume_recursie[100];
printf("Dati numele de case 5:
cautare: "); menu_4 = 0;
fflush(stdin); break;

strupr(gets(nume_recursie)); default:
printf("Error: Acesta
nod *ttt; optiune nu exista !");
ttt = searchSDA(root, getch();
nume_recursie); break;
printf("\nCinematograf }
cautat : \n\n"); }
if (ttt)
{
printf("Denumirea: }
\"%s\"\n", strupr(ttt->name));
printf("Adresa: %s\n", return 0;
strupr(ttt->adress)); }
Introducerea arborelui:

Meniu principal:
Concluzii:
In urma efectuarii laboratorului am facut cunostinta cu notiunele de stiva,
coada , arbore si altele. Am obtinut deprinderi practice de prelucrarea arborilor
binari, crearea cozilor si stivelor. Am invatat cum sa aplic in practica algoritmii
iterativi si recursivi pentru crearea, parcurgerea si prelucrearea arborilor.
Coada este o structura de date foarte necesara in programare. Cu ajutorul ei
putem realiza algorimii sau, de exemplu lista de asteptare pentru diferite lucruri.
Algorimtii recursivi cere de la programator atentie sporita, fiindca daca ati
uitat sa scrieti conditia de iesire din recursia, ea se fa efectua nelimitat.
A doua problema recursiei reisese din prima. Daca resucrisia n-are conditia
de stopare, atunci progrmaul va folosi toate resursele calculatorului, innaine de a
da eroare.
Algorimii recursivi sunt foarte complicate penru intelegerea, daca sinteti
incepetor. Totusi pentru un programist avansat este un instrument foarte puternic.

Bibliografie:
1. Informaii despre Stiv (structura de date)(http://www.cs.utah.edu/~regehr/stacktool/)
[Accesat la 21.05.2017]
2. Informatii despre Cozi (https://xlinux.nist.gov/dads/HTML/queue.html)
[Accesat la 21.05.2017]
3. Conspect la curs Structuri de Date si Algoritmii