Sunteți pe pagina 1din 20

Arbori binari (C++ partea 6)

1. Arbori binari.........................................................................................................................3 1.1. Crearea i parcurgerea RSD, SRD, SDR (afiarea) unui arbore binar..........................6 1.2. tergerea unui nod dintr-un arbore binar.....................................................................10 1.3. Inserarea unui nod ntr-un arbore binar.......................................................................12 1.4. Numrarea nodurilor i determinarea numrului de niveluri......................................14 1.5. Programul complet......................................................................................................15

Nchil Ctlin Laborator UPG

Arbori binari (C++ partea 6)

1. Arbori binari
Un arbore binar este un arbore n care fiecare vrf are cel mult doi descendeni fcndu-se distincie clar ntre descendentul drept i descendentul stng al fiecrui vrf. Pentru discuiile referitoare la arbori este necesar o terminologie special: fiecare element este numit nod; primul element dintr-un arbore se numete rdcin; celelalte noduri formeaz fiecare cte un arbore; aceti arbori se numesc subarbori; ntr-un arbore exist noduri crora nu le mai corespund subarbori; un astfel de nod se numete nod terminal sau frunz; un nod rdcin este numit nod tat; rdcina unui subarbore se numete nod fiu; rdcina unui arbore se afl pe nivelul 1; dac un nod are nivelul m atunci fii lui au nivelul m + 1; prin nlimea arborelui nelegem numrul total de niveluri al unui arbore determin . Un arbore binar n care fiecare nod care nu este terminal are exact doi descendeni se numete arbore binar complet. Pentru utilizarea nodurilor unui arbore binar vom folosi o structura cu urmtoarele cmpuri: inf informaia coninuta in nod st adresa nodului descendent stng; dr adresa nodului descendent drept.

struct NOD { int inf; struct NOD *st,*dr; };

Nchil Ctlin Laborator UPG

Arbori binari (C++ partea 6) Exemplul 1 (Structura unui arbore):

Prin parcurgerea (traversarea) unui arbore se nelege examinarea n mod sistematic a nodurilor sale astfel nct fiecare nod sa fie parcurs o singura dat. Exist trei moduri de parcurgere (recursiv) a arborilor binari: a) Preordine (RSD) se viziteaz rdcina; se traverseaz arborele stng; se traverseaz arborele drept. c) Postordine (SDR) se traverseaz arborele stng; se traverseaz arborele drept; se viziteaz rdcina. b) Inordine (SRD) se traverseaz arborele stng; se viziteaz rdcina; se traverseaz arborele drept.

Nchil Ctlin Laborator UPG

Arbori binari (C++ partea 6)

Exemplul 1 (Parcurgere): Fie arborele:

parcurs n preordine (RSD): parcurs n inordine (SRD): parcurs n postordine (SDR):

1, 2, 4, 5, 3, 6, 7, 8; 4, 5, 2, 1, 6, 3, 8, 7; 5, 4, 2, 6, 8, 7, 3, 1.

Exemplul 2 (Structura unui arbore & Parcurgere): Fie arborele:

parcurs n preordine: parcurs n inordine:

10, 7, 3, 9, 8, 15, 25; 3, 7, 8, 9, 10, 15, 25;

parcurs n postordine: 3, 8, 9, 7, 25, 15, 10.

Nchil Ctlin Laborator UPG

Arbori binari (C++ partea 6) Structura arborelui:

1.1. Crearea i parcurgerea RSD, SRD, SDR (afiarea) unui arbore binar
# # # # # include <stdio.h> include <conio.h> include <alloc.h> include <stdlib.h> define NEW (NOD*)malloc(sizeof(NOD));

struct NOD { int inf; struct NOD *st,*dr; }; /////////////////// Crearea arborelui by nec NOD *creare() { NOD *p; int nr; p=NEW; printf("Nr="); scanf("%d",&nr); p->inf=nr; p->st=NULL;

Nchil Ctlin Laborator UPG

Arbori binari (C++ partea 6) p->dr=NULL; printf("Introducem arbore in stanga pentru nodul cu informatia %d (d/n)? \n",nr); if(getch()=='d') p->st=creare(); printf("Introducem arbore in dreapta pentru nodul cu informatia %d (d/n)? \n",nr); if(getch()=='d') p->dr=creare(); return p;} /////////////////// Parcurgerea RSD arborelui by nec void parc_preord (NOD *p) { if(p!=NULL) { printf("\t Nr=%d", p->inf); parc_preord(p->st); parc_preord(p->dr); } } /////////////////// Parcurgerea SRD arborelui by nec void parc_inord (NOD *p) { if(p!=NULL) { parc_inord(p->st); printf("\t Nr=%d", p->inf); parc_inord(p->dr); } }

/////////////////// Parcurgerea SDR arborelui by nec void parc_postord (NOD *p) { if(p!=NULL) { parc_postord(p->st); parc_postord(p->dr); printf("\t Nr=%d", p->inf); } } Nchil Ctlin Laborator UPG 7

Arbori binari (C++ partea 6) /////////////////// Stergerea arborelui by nec void stergarbore(NOD *p) { if (p!=NULL) { stergarbore(p->st); stergarbore(p->dr); delete p; } } /////////////////// Afisare spatii by nec void spatii(int n) { int i; for(i=0;i<n;i++) putchar(' '); } /////////////////// Afisare arbore by nec void afisare(int n, int f, int k, int vb, int *vn) { int i; spatii(4); if(n) { for(i=1;i<n;i++) { if(vn[i]) putchar(' '); else putchar('|'); spatii(4); } if(f) putchar('|'); else putchar('|'); for(i=0;i<4;i++) putchar('-'); } if(vb) printf("%d\n",k); else printf("...\n"); }

Nchil Ctlin Laborator UPG

Arbori binari (C++ partea 6)

/////////////////// Afisare pe niveluri by nec void afisare_nivel (NOD *p, int n=0) { static int vn[50],f=1; if(p) { afisare(n,f,p->inf,1,vn); if(p->st || p->dr) { f=1; vn[n+1]=0; afisare_nivel(p->st,n+1); } if(p->st || p->dr) { f=0; vn[n+1]=1; afisare_nivel(p->dr,n+1); } } else afisare(n,f,10,0,vn);} /////////////////// Programul principal by nec void main() {NOD *rad; int nr,nivel,nrnou,nrsters; clrscr(); rad=creare(); printf("--------------------------------------------------- \n"); printf("Parcurgere preordine \n"); parc_preord(rad);printf("\n"); printf("Parcurgere inordine \n"); parc_inord(rad);printf("\n"); printf("Parcurgere postordine \n"); parc_postord(rad);printf("\n"); printf("\n"); printf("Afisarea pe niveluri: \n"); afisare_nivel(rad); Nchil Ctlin Laborator UPG 9

Arbori binari (C++ partea 6) printf("\n");getchar();getchar();}

1.2. tergerea unui nod dintr-un arbore binar


Aceasta operaie va avea n vedere faptul c dup efectuarea tergerii nodului dorit, arborele va trebui s rmn tot arbore binar. Funcia de tergere a unui nod trebuie mai nti sa efectueze cutarea nodului cu informaia util dorit. tergerea efectiva a nodului va avea dou cazuri: Cazul 1) Nodul de ters are cel puin un descendent vid , caz n care se reactualizeaz legtura nodului printe i se terge fizic nodul (funcia din program este stergerenod):

Cazul 2) Nodul de ters are doi fii . Nodul respectiv nu se va terge fizic.Informaia lui va fi nlocuit cu informaia celui mai din stnga nod al subarborelui drept sau cu informaia a celui mai din dreapta nod al subarborelui stng, care apoi va fi ters (nodul are informaia imediat mai mare, respectiv imediat mai mic, dect informaia nodului ce va trebui ters, deci arborele n ansamblu va rmne tot de cutare) (funcia din program este sterg):

Funcia va returna informaia nodului care se va terge fizic pentru a nlocui informaia nodului cutat pentru a fi ters. Nchil Ctlin Laborator UPG 10

Arbori binari (C++ partea 6)

Funcia de tergere a unui nod este: ///////////////// Stergerea unui nod cu doi descendenti by nec int sterg(NOD *&pa) { if(pa->st) return sterg(pa->st); else { NOD *a=pa; int k=a->inf; pa=pa->dr; free(a); return k; } } ///// Stergerea unui nod cu cel putin nu descendent vid by nec void stergerenod(NOD *& p, int k) { NOD *aux; if(p==NULL) printf("\n Nodul %d nu exista ",p->inf); else if(k<p->inf) stergerenod(p->st,k); else if(k>p->inf) stergerenod(p->dr,k); else { aux=p; if(!aux->dr) { p=aux->st; free(aux); } else if(!aux->st) { p=aux->dr; free(aux); } else p->inf=sterg(p->dr); } } Nchil Ctlin Laborator UPG 11

Arbori binari (C++ partea 6) n programul principal se va aduga secvena: printf("----------------------------------------------- \n"); printf("Nodul care se sterge = "); scanf("%d",&nrsters); stergerenod(rad,nrsters); printf("Parcurgere preordine \n"); parc_preord(rad);printf("\n"); printf("Parcurgere inordine \n"); parc_inord(rad);printf("\n"); printf("Parcurgere postordine \n"); parc_postord(rad);printf("\n"); printf("Afisarea pe niveluri: \n"); afisare_nivel(rad);

1.3. Inserarea unui nod ntr-un arbore binar


Fie arborele:

Inserm nodurile 2, 4, 8, 11, 16, 30. Poziia lor va fi urmtoarea:

Nchil Ctlin Laborator UPG

12

Arbori binari (C++ partea 6)

Funcia de inserare a unui nod este: /////////////////// Inserare nod by nec void inserare(NOD *&p,int x) {NOD *pnou; if (p==NULL) { pnou=NEW pnou->inf=x; pnou->st=NULL; pnou->dr=NULL; p=pnou; } else if (p->inf>x) inserare(p->st,x); else if (p->inf<x) inserare(p->dr,x); else printf("Elementul deja exista! \n"); } n programul principal se va aduga secvena: printf("--------------------------------------------------- \n"); printf("Numarul de inserat este="); scanf("%d",&nrnou); inserare(rad,nrnou); printf("Parcurgere preordine \n"); parc_preord(rad);printf("\n"); printf("Parcurgere inordine \n"); parc_inord(rad);printf("\n"); printf("Parcurgere postordine \n"); parc_postord(rad);printf("\n"); printf("Afisarea pe niveluri: \n"); afisare_nivel(rad);

Nchil Ctlin Laborator UPG

13

Arbori binari (C++ partea 6)

1.4. Numrarea nodurilor i determinarea numrului de niveluri


Funciile sunt: /////////////////// Maximul dintre doua nr by nec int max(int x,int y) { if (x<y) return y; else return x; } /////////////////// Numararea nodurilor arborelui by nec int nrnod(NOD *p) { if(p!=NULL) return 1+nrnod(p->st)+nrnod(p->dr); else return 0; } //////// Determinarea numarului de niveluri ale arborelui by nec int inaltime(NOD *p) { int stanga, dreapta; if(p!=NULL) return 1+max(inaltime(p->st),inaltime(p->dr)); else return 0; } n programul principal se va aduga secvena: nr=nrnod(rad); printf("Numarul de noduri este=%d \n",nr); nivel=inaltime(rad); printf("Inaltimea este=%d \n",nivel);

Nchil Ctlin Laborator UPG

14

Arbori binari (C++ partea 6)

1.5. Programul complet


# include <stdio.h> # include <conio.h> # include <alloc.h> # include <stdlib.h> # define NEW (NOD*)malloc(sizeof(NOD)); struct NOD { int inf; struct NOD *st,*dr; }; /////////////////// Crearea arborelui by nec NOD *creare() { NOD *p; int nr; p=NEW; printf("Nr="); scanf("%d",&nr); p->inf=nr; p->st=NULL; p->dr=NULL; printf("Introducem arbore in stanga pentru nodul cu informatia %d (d/n)? \n",nr); if(getch()=='d') p->st=creare(); printf("Introducem arbore in dreapta pentru nodul cu informatia %d (d/n)? \n",nr); if(getch()=='d') p->dr=creare(); return p;} /////////////////// Parcurgerea RSD arborelui by nec void parc_preord (NOD *p) {if(p!=NULL) { printf("\t Nr=%d", p->inf); parc_preord(p->st); parc_preord(p->dr); } }

Nchil Ctlin Laborator UPG

15

Arbori binari (C++ partea 6)

/////////////////// Parcurgerea SRD arborelui by nec void parc_inord (NOD *p) { if(p!=NULL) { parc_inord(p->st); printf("\t Nr=%d", p->inf); parc_inord(p->dr); } } /////////////////// Parcurgerea SDR arborelui by nec void parc_postord (NOD *p) { if(p!=NULL) { parc_postord(p->st); parc_postord(p->dr); printf("\t Nr=%d", p->inf); } } /////////////////// Stergerea arborelui by nec void stergarbore(NOD *p) { if (p!=NULL) { stergarbore(p->st); stergarbore(p->dr); delete p; } } /////////////////// Afisare spatii by nec void spatii(int n) { int i; for(i=0;i<n;i++) putchar(' '); }

Nchil Ctlin Laborator UPG

16

Arbori binari (C++ partea 6)

/////////////////// Afisare arbore by nec void afisare(int n, int f, int k, int vb, int *vn) {int i; spatii(4); if(n) { for(i=1;i<n;i++) { if(vn[i]) putchar(' '); else putchar('|'); spatii(4); } if(f) putchar('|'); else putchar('|'); for(i=0;i<4;i++) putchar('-'); } if(vb) printf("%d\n",k); else printf("...\n"); } /////////////////// Afisare pe nivele by nec void afisare_nivel (NOD *p, int n=0) {static int vn[50],f=1; if(p) { afisare(n,f,p->inf,1,vn); if(p->st || p->dr) { f=1; vn[n+1]=0; afisare_nivel(p->st,n+1); } if(p->st || p->dr) { f=0; vn[n+1]=1; afisare_nivel(p->dr,n+1); } } else afisare(n,f,10,0,vn); } Nchil Ctlin Laborator UPG 17

Arbori binari (C++ partea 6)

///////////////// Stergerea unui nod cu doi descendenti by nec int sterg(NOD *&pa) { if(pa->st) return sterg(pa->st); else { NOD *a=pa; int k=a->inf; pa=pa->dr; free(a); return k; } } ///// Stergerea unui nod cu cel putin nu descendent vid by nec void stergerenod(NOD *& p, int k) { NOD *aux; if(p==NULL) printf("\n Nodul %d nu exista ",p->inf); else if(k<p->inf) stergerenod(p->st,k); else if(k>p->inf) stergerenod(p->dr,k); else { aux=p; if(!aux->dr) { p=aux->st; free(aux); } else if(!aux->st) { p=aux->dr; free(aux); } else p->inf=sterg(p->dr); } }

Nchil Ctlin Laborator UPG

18

Arbori binari (C++ partea 6)

/////////////////// Inserare nod by nec void inserare(NOD *&p,int x) {NOD *pnou; if (p==NULL) { pnou=NEW pnou->inf=x; pnou->st=NULL; pnou->dr=NULL; p=pnou; } else if (p->inf>x) inserare(p->st,x); else if (p->inf<x) inserare(p->dr,x); else printf("Elementul deja exista! \n"); } /////////////////// Maximul dintre doua nr by nec int max(int x,int y) {if (x<y) return y; else return x; } /////////////////// Numararea nodurilor arborelui by nec int nrnod(NOD *p) {if(p!=NULL) return 1+nrnod(p->st)+nrnod(p->dr); else return 0; } //////// Determinarea numarului de niveluri ale arborelui by nec int inaltime(NOD *p) {int stanga, dreapta; if(p!=NULL) return 1+max(inaltime(p->st),inaltime(p->dr)); else return 0; } Nchil Ctlin Laborator UPG 19

Arbori binari (C++ partea 6)

/////////////////// Programul principal by nec void main() { NOD *rad; int nr,nivel,nrnou,nrsters; clrscr();

///// Crearea si afisarea RSD, SRD, SDR a unui arbore by nec rad=creare(); printf("--------------------------------------------------- \n"); printf("Parcurgere preordine \n"); parc_preord(rad);printf("\n"); printf("Parcurgere inordine \n"); parc_inord(rad);printf("\n"); printf("Parcurgere postordine \n"); parc_postord(rad);printf("\n"); printf("\n"); printf("Afisarea pe niveluri: \n"); afisare_nivel(rad); printf("\n");

///// Stergerea unui nod by nec printf("--------------------------------------------------- \n"); printf("Nodul care se sterge = "); scanf("%d",&nrsters); stergerenod(rad,nrsters); printf("Parcurgere preordine \n"); parc_preord(rad);printf("\n"); printf("Parcurgere inordine \n"); parc_inord(rad);printf("\n"); printf("Parcurgere postordine \n"); parc_postord(rad);printf("\n"); printf("Afisarea pe niveluri: \n"); afisare_nivel(rad);

Nchil Ctlin Laborator UPG

20

Arbori binari (C++ partea 6)

///// Inserarea unui nod by nec printf("--------------------------------------------------- \n"); printf("Numarul de inserat este="); scanf("%d",&nrnou); inserare(rad,nrnou); printf("Parcurgere preordine \n"); parc_preord(rad);printf("\n"); printf("Parcurgere inordine \n"); parc_inord(rad);printf("\n"); printf("Parcurgere postordine \n"); parc_postord(rad);printf("\n"); printf("Afisarea pe niveluri: \n"); afisare_nivel(rad); ///// Nr. noduri & nr. niveluri by nec nr=nrnod(rad); printf("Numarul de noduri este=%d \n",nr); nivel=inaltime(rad); printf("Inaltimea este=%d \n",nivel);

getchar();getchar(); }

Nchil Ctlin Laborator UPG

21