Sunteți pe pagina 1din 6

Tehnici Avansate de Programare

Laborator 7

Arbori

1. Conţinutul lucrării
În lucrare sunt prezentate operaţiile de bază asupra arborilor binari, binari total echilibraţi şi
arborilor oarecare.

2. Consideraţii teoretice
Arborele binar, foarte des întâlnit în aplicaţii, este arborele în care orice nod are cel mult doi
descendenţi: fiul stâng şi fiul drept.

2.1. Construirea, traversarea şi ştergerea unui arbore binar.


Construirea unui arbore binar se face citind în preordine din fişierul de intrare informaţiile din
nodurile arborelui. Subarborii vizi trebuie să fie notaţi cu un semn distinctiv. De exemplu pentru arborele
din figura 2.1.1, notând identificatorul pentru arborele vid cu * , introducerea identificatorilor nodurilor
se va face astfel:

ABD*G***CE**F*H**

Fig. 2.1.1. Arbore binar.

Tipul unui nod se declară astfel:


typedef struct tip_nod {
char ch; /* identificatorul nodului */
informaţie;
struct tip_nod *stg, *dr;
} TIP_NOD;

Construirea unui arbore binar se face conform funcţiei de construire, având următoarea structură:

TIP_NOD *construire( )
{
TIP_NOD *p;
int n;
char c;
n=sizeof(TIP_NOD);
/* citire caracter de identificare nod */
scanf(“%c”, c);
if(c==’*’) return 0;
else {
/* construire nod de adresă p */
p=(TIP_NOD *)malloc(n);
/* introducere de informaţie în nod */
p->ch=c;
p->stg=construire( );
p->dr=construire( );
}
return p;
}
Apelul funcţiei se va face astfel:
rădăcina = construire ( )
Traversarea unui arbore binar se poate face în cele 3 moduri cunoscute: preordine, inordine,
postordine.
În programul următor sunt implementate operaţiile de construcţie şi traversare a unui arbore binar.
Nodul conţine numai identificatorul său. Afişarea nodurilor vizitate se face cu indentare.
/* Program de construire şi afişare a arborilor binari */
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
typedef struct tip_nod{
int nr.; /*informaţie */
struct tip_nod *stg,*dr;
} TIP_NOD;
TIP_NOD *rad;
void preordine(TIP_NOD *p, int nivel)
{
int i;
if (p!=0){
for(i=0;i<=nivel;i++) printf(" ");
printf("%2d\n",p->nr);
preordine(p->stg,nivel+1);
preordine(p->dr,nivel+1);
}
}
void inordine(TIP_NOD *p, int nivel)
{
int i;
if (p!=0){
inordine(p->stg,nivel+1);
for(i=0;i<=nivel;i++) printf(" ");
printf("%2d\n",p->nr);
inordine(p->dr,nivel+1);
}
}
void postordine(TIP_NOD *p, int nivel)
{
int i;
if (p!=0){
postordine(p->stg,nivel+1);
postordine(p->dr,nivel+1);
for(i=0;i<=nivel;i++) printf(" ");
printf("%2d\n",p->nr);
}
}
TIP_NOD *constructie()
{
TIP_NOD *p;
int inf,n;
n=sizeof(TIP_NOD);
printf("\nIntroduceti Inf.din nod inf=");
scanf("%d",&inf);
if(inf==0) return 0;
else {
p=(TIP_NOD *)malloc(n);
p->nr=inf;
p->stg=constructie();
p->dr=constructie();
}
return p;
}

void main(void)
{
rad=constructie();
printf("\nVIZITAREA IN PREORDINE\n");
preordine(rad,0);
getch();
printf("\nVIZITAREA IN INORDINE\n");
inordine(rad,0);
getch();
printf("VIZITAREA IN POSTORDINE\n");
postordine(rad,0);
getch();
}
2.1 Arbori binari total echilibraţi
Un arbore binar total echilibrat este un arbore binar care îndeplineşte următoarea condiţie: numărul
nodurilor unui oricare subarbore stâng diferă cu cel mult 1 în plus faţă de numărul nodurilor subarborelui
corespunzător drept. Rezultă că frunzele sale se află pe ultimele două niveluri.
Algoritmul de construire a unui arbore binar total echilibrat cu n noduri, este următorul:
a) un nod este rădăcină;
b) se iau nstg = [n/2] noduri pentru arborele stâng şi se trece la construirea lui (pasul a);
c) se iau cele ndr=n-nstg-1 noduri rămase pentru subarborele drept şi se trece la construirea lui
(pasul a).
Pentru oricare nod există relaţia:
ndr <= nstg <= ndr + 1
În programul următor este implementat acest algoritm pentru construirea unui arbore binar total
echilibrat, citirea informaţiei în noduri făcându-se în preordine.

#include <stdio.h>
#include <conio.h>
#include <alloc.h>
/* ARBORI BINARI TOTAL ECHILIBRATI */

typedef struct tip_nod{


int nr;/*informaţie */
struct tip_nod *stg,*dr;
} TIP_NOD;
TIP_NOD *rad;
void preordine(TIP_NOD *p, int nivel)
{
int i;
if(p!=0) {
for(i=0;i<=nivel;i++) printf(" ");
printf("%2d\n",p->nr);
preordine(p->stg,nivel+1);
preordine(p->dr,nivel+1);
}
}
void inordine(TIP_NOD *p, int nivel)
{
int i;
if (p!=0){
inordine(p->stg,nivel+1);
for(i=0;i<=nivel;i++) printf(" ");
printf("%2d\n",p->nr);
inordine(p->dr,nivel+1);
}
}
void postordine(TIP_NOD *p, int nivel)
{
int i;
if (p!=0){
postordine(p->stg,nivel+1);
postordine(p->dr,nivel+1);
for(i=0;i<=nivel;i++) printf(" ");
printf("%2d\n",p->nr);
}
}
TIP_NOD *constructie(int nr_noduri)
{
TIP_NOD *p;
int n_stg,n_dr;
int inf,n;
n=sizeof(TIP_NOD);
if(nr_noduri==0) return 0;
else {
n_stg=nr_noduri/2;
/*nr_noduri din subarborele stang */
n_dr=nr_noduri-n_stg-1;
/*nr.noduri din subarborele drept */
p=(TIP_NOD *)malloc(n);
printf("\nIntroduceti informatia din nod in preordine ");
scanf("%d",&(p->nr));
p->stg=constructie(n_stg);
p->dr=constructie(n_dr);
}
return p;
}

void main(void)
{
int nr_total_noduri;
printf("\nNumarul total de noduri =");
scanf("%d",&nr_total_noduri);\
rad=constructie(nr_total_noduri);
printf("\nVIZITAREA IN PREORDINE\n");
preordine(rad,0);
getch();
printf("\nVIZITAREA IN INORDINE\n");
inordine(rad,0);
getch();
printf("VIZITAREA IN POSTORDINE\n");
postordine(rad,0);
getch();
}
2.2 Arbori oarecare

Arborele oarecare este un arbore a cărui noduri au mai mult de doi descendenţi.
Un nod are următoarea structură:

typedef struct tip_nod {


informaţie;
int nr_fii; /*număr de fii */
struct tip_nod *adr_fii [maxfii];
/* adresele nodurilor fiu */
} TIP_NOD;
Construirea arborelui se realizează astfel:
 pentru fiecare nod se citeşte informaţia utilă şi numărul de fii;
 nodurile citite în postordine şi adresele sunt păstrate într-o stivă până când apare nodul al cărui fii
sunt. În acest moment adresele fiilor sunt scoase din stivă, iar adresele lor sunt trecute în nodul tată, după
care adresa nodului tată este pusă în stivă. În final singura adresă în stivă va fi cea a rădăcinii, arborele
fiind construit.
Traversarea arborelui pe orizontală (nivel după nivel) se va face astfel:
 se utilizează o coadă pentru păstrarea adreselor nodurilor ce urmează să fie prelucrate;
 iniţial coada este vidă;
 se introduce în coada adresa rădăcinii;
 se scoate pe rând din coadă adresa a câte unui nod, se prelucrează informaţia din nod, iar apoi se
introduc adresele fiilor nodului respectiv. Se repetă acest pas până când coada devine vidă.

3. Mersul lucrării

3.1 Se citeşte de la tastatură o expresie matematică în formă postfixată, sub forma unui şir de caractere.
Să se construiască arborele corespunzător acestei expresii, fiecare nod conţinând un operator sau un
operand.

3.2 Să se tipărească expresia de la punctul 3.1. în formă postfixată şi infixată.

3.3 Să se evalueze expresia matematică de la punctul 3.1.

3.4 Să se evalueze un arbore care conţine în noduri constantele 0 şi 1 şi operatorii AND, OR, NOT.

3.5 Să se scrie funcţii de pretty-print (tipărire frumoasă) a arborilor.

3.6 Să se scrie funcţii nerecursive pentru traversarea arborilor.

3.7 Arborele genealogic al unei persoane se reprezintă astfel: numele persoanei este cheia nodului
rădăcină şi pentru fiecare nod cheia descendentului stâng este numele tatălui, iar a descendentului drept
este numele mamei. Se citesc două nume de la tastatură. Ce relaţie de rudenie există între cele două
persoane? Se presupune că o familie are doar un singur fiu.

3.8 Să se scrie un program care transformă un arbore binar într-o listă dublu înlănţuită.

3.9 Să se scrie un program care să interschimbe subarborele drept cu cel stâng pentru un nod dat.

3.10 Să se scrie o funcţie care determină înălţimea unui arbore binar.


3.11 Să se scrie o funcţie care determină numărul de frunze ale unui arbore binar.

3.12 Să se scrie o funcţie care determină dacă doi arbori binari sunt echivalenţi (arborii binari sunt
echivalenţi dacă sunt structural echivalenţi şi datele corespunzătoare nodurilor sunt aceleaşi).

3.13 Să se scrie un program de construire şi traversare a unui arbore oarecare conform indicaţiilor din
lucrare (paragraful 2.3.).

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