Arbori. Figura 1. struct ANOD { int val; ANOD* st; ANOD* dr; }; #include <stdio.h> #include <conio.h> struct ANOD { int val; ANOD* st; ANOD* dr; }

Similar documents
ARBORI AVL. (denumiti dupa Adelson-Velskii si Landis, 1962)

Structuri de date: ARBORI

APLICAŢII ELEMENTARE CU ARBORI

Reflexia şi refracţia luminii. Aplicaţii. Valerica Baban

Titlul lucrării propuse pentru participarea la concursul pe tema securității informatice

Metrici LPR interfatare cu Barix Barionet 50 -

Procesarea Imaginilor

Grafuri bipartite. Lecție de probă, informatică clasa a XI-a. Mihai Bărbulescu Facultatea de Automatică și Calculatoare, UPB

Subiecte Clasa a VI-a

2. Setări configurare acces la o cameră web conectată într-un router ZTE H218N sau H298N

Structura și Organizarea Calculatoarelor. Titular: BĂRBULESCU Lucian-Florentin

HEAPSORT I. CONSIDERAŢII TEORETICE

Ghid identificare versiune AWP, instalare AWP şi verificare importare certificat în Store-ul de Windows

Olimpiad«Estonia, 2003

Textul si imaginile din acest document sunt licentiate. Codul sursa din acest document este licentiat. Attribution-NonCommercial-NoDerivs CC BY-NC-ND

Semnale şi sisteme. Facultatea de Electronică şi Telecomunicaţii Departamentul de Comunicaţii (TC)

Dispozitive Electronice şi Electronică Analogică Suport curs 02 Metode de analiză a circuitelor electrice. Divizoare rezistive.

Versionare - GIT ALIN ZAMFIROIU

Modalitǎţi de clasificare a datelor cantitative

Update firmware aparat foto

Mecanismul de decontare a cererilor de plata

Mircea Merca 1) Articol dedicat Prof. Dr. Ioan Tomescu la a 70-a aniversare

D în această ordine a.î. AB 4 cm, AC 10 cm, BD 15cm

Managementul referinţelor cu

The First TST for the JBMO Satu Mare, April 6, 2018

CERERI SELECT PE O TABELA

Metoda BACKTRACKING. prof. Jiduc Gabriel

Auditul financiar la IMM-uri: de la limitare la oportunitate

Platformă de e-learning și curriculă e-content pentru învățământul superior tehnic

GHID DE TERMENI MEDIA

2. Tipul referinţă, structuri de date dinamice ( liste înlănţuite şi arbori binari).

La fereastra de autentificare trebuie executati urmatorii pasi: 1. Introduceti urmatoarele date: Utilizator: - <numarul dvs de carnet> (ex: "9",

Mods euro truck simulator 2 harta romaniei by elyxir. Mods euro truck simulator 2 harta romaniei by elyxir.zip

Metode de acces la informatie în bazele de date pentru prelucrari grafice

Algoritmi pentru regăsirea informaţiei

Reţele Neuronale Artificiale în MATLAB

În continuare vom prezenta unele dintre problemele de calcul ale numerelor Fibonacci.

Baze de date distribuite și mobile

REVISTA NAŢIONALĂ DE INFORMATICĂ APLICATĂ INFO-PRACTIC

Aspecte controversate în Procedura Insolvenţei şi posibile soluţii

ISBN-13:

1. Creaţi un nou proiect de tip Windows Forms Application, cu numele MdiExample.

MS POWER POINT. s.l.dr.ing.ciprian-bogdan Chirila

CHAMPIONS LEAGUE 2017 SPONSOR:

C10. Structuri de date dinamice / Arbori binari 1/57

Arbori sistolici binari

Lucrarea de laborator nr. 4

Ce pot face pe hi5? Organizare si facilitati. Pagina de Home

X-Fit S Manual de utilizare

Vizualizarea documentelor xml

Capitolul 4 SUBCERERI. F. Radulescu. Curs: Baze de date - Limbajul SQL

CERERI SELECT PE MAI MULTE TABELE

CAIETUL DE SARCINI Organizare evenimente. VS/2014/0442 Euro network supporting innovation for green jobs GREENET

Itemi Sisteme de Operare

Propuneri pentru teme de licență

Excel Advanced. Curriculum. Școala Informală de IT. Educație Informală S.A.

Proiectarea bazelor de date. PL/SQL Înregistrări și Colecții # 13. Adrian Runceanu

INTEROGĂRI ÎN SQL SERVER

PROIECTAREA ALGORITMILOR

MICROSOFT ACCESS 2007 (DE CĂUTAT???)

Documentaţie Tehnică

Printesa fluture. Мобильный портал WAP версия: wap.altmaster.ru

9. Memoria. Procesorul are o memorie cu o arhitectură pe două niveluri pentru memoria de program și de date.

Proceduri stocate. Crearea procedurilor stocate. Varianta 1 În Management Studio se dă clic pe New Query ca în imaginea de mai jos: Fig.

Nume şi Apelativ prenume Adresa Număr telefon Tip cont Dobânda Monetar iniţial final

6. Bucle. 6.1 Instrucţiunea while

EN teava vopsita cu capete canelate tip VICTAULIC

Candlesticks. 14 Martie Lector : Alexandru Preda, CFTe

MODELUL UNUI COMUTATOR STATIC DE SURSE DE ENERGIE ELECTRICĂ FĂRĂ ÎNTRERUPEREA ALIMENTĂRII SARCINII

Tratarea excepţiilor

Tema 1 - Transferuri de date DMA intr-o arhitectura de tip Cell

Prima. Evadare. Ac9vity Report. The biggest MTB marathon from Eastern Europe. 7th edi9on

2. Setări configurare acces la o cameră web conectată într-un echipament HG8121H cu funcție activă de router

Strategii pentru jocul de dame Dame Inteligente

DE CE SĂ DEPOZITAŢI LA NOI?

INFORMAȚII DESPRE PRODUS. FLEXIMARK Stainless steel FCC. Informații Included in FLEXIMARK sample bag (article no. M )

Funcţii grup şi clauzele GROUP BY, HAVING. Operatorii ROLLUP şi CUBE.

Decizia manageriala în conditii de risc. Profilul riscului.

KAJOT V.RO BLACK PLANET JOC DE NOROC CU RISC LIMITAT


Actualizarea firmware-ului pentru aparatul foto digital SLR

Laborator 1. Programare declarativă. Programare logică. Prolog. SWI-Prolog

The driving force for your business.

Creare baza de data Deschidem aplicaţia Microsoft Access. Lansarea în execuţie a programului se face urmând calea:

Generarea şi validarea numerelor prime mari

LINEAR VOLTAGE-TO-CURRENT CONVERTER WITH SMALL AREA

Platformă de e-learning și curriculă e-content pentru învățământul superior tehnic

I. Instrucţiuni PRELEGERE IX PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE

2. In the pattern below, which number belongs in the box? 0,5,4,9,8,13,12,17,16, A 15 B 19 C 20 D 21

Laboratorul 3 Lucrul cu baze de date relaționate în Visual C#.NET

Updating the Nomographical Diagrams for Dimensioning the Concrete Slabs

9. CURSOARE. Obiective. În acest Capitol, vom învăţa despre: Manipularea cursoarelor. Folosirea Cursor FOR Loops şi Nesting Cursors.

PROCEDURA PRIVIND DECONTURILE. 2. Domeniu de aplicare Procedura se aplică în cadrul Universităţii Tehnice Cluj-Napoca

F. Radulescu. Curs: Utilizarea bazelor de date, anul IV C5.

Proiectarea Sistemelor Software Complexe

Subinterogari SELECT salariul FROM angajaţi WHERE nume= Ionescu SELECT nume, prenume FROM angajaţi WHERE salariul>s

ANALIZA FUNCŢIONALĂ, O METODĂ DE MODELARE ÎN PROIECTAREA UTILAJELOR

A NOVEL ACTIVE INDUCTOR WITH VOLTAGE CONTROLLED QUALITY FACTOR AND SELF-RESONANT FREQUENCY

Preţul mediu de închidere a pieţei [RON/MWh] Cota pieţei [%]

Mai bine. Pentru c putem.

Transcription:

Arbori Arborii, ca şi listele, sunt structuri dinamice. Elementele structurale ale unui arbore sunt noduri şi arce orientate care unesc nodurile. Deci, în fond, un arbore este un graf orientat degenerat. Există mai multe tipuri de arbori, dar de o importanţă deosebită sunt arborii binari. Aceştia se caracterizează prin faptul că fiecare nod poate avea doar două noduri copil, rezultând o structură ca în fig. 1, în care prin cercuri sunt reprezentate nodurile, iar prin săgeţi arcele. Primul nod din arbore se numeşte nod rădăcină, iar nodurile finale pe fiecare ramură a arborelui se numesc noduri frunze. Din cele arătate mai sus rezultă că un nod este descris de structura de mai jos: struct ANOD int val; ANOD* st; ANOD* dr; ; unde val este valoarea conţinută de nodul respectiv, st este un pointer spre fiul stâng al nodului respectiv (NULL dacă nu există nici un nod fiu stâng) şi dr este un pointer spre fiul stâng al nodului respectiv (NULL dacă nu există nici un nod fiu drept). Pentru a pregăti crearea unui arbore, vom scrie următoarea secvenţă de program: #include <stdio.h> #include <conio.h> struct ANOD int val; ANOD* st; ANOD* dr; void main(void) clrscr(); ANOD* radacina=null; Figura 1 Prin aceasta, am declarat un pointer care va pointa spre rădăcina arborelui. Cum în acest stadiu arborele nu are nici un nod, acest pointer va fi NULL. Similar listelor, asupra arborilor se pot defini mai multe operaţii, cum ar fi: - inserarea unui nod în arbore; - ştergerea unui nod frunză într-un arbore; - parcurgerea arborelui; - căutarea unui nod din arbore. 1

Operaţiile de inserare şi căutare vor fi făcute pe baza unui criteriu, care precizează poziţia în arbore (stânga, dreapta) şi valoarea nodului la care se adaugă nodul fiu, respectiv direcţia de căutare în arbore a nodului dorit. În general acest criteriu nu este unic şi depinde de modul în care utilizatorul doreşte să implementeze arborele. În exemplul nostru, se propune o funcţie criteriu cu implementarea de mai jos: int criteriu(anod* p1, ANOD* p2) if (p1->val > p2->val) return -1; if (p1->val < p2->val) return 1; return 0; Funcţia primeşte ca argumente doi parametri de tip nod şi returnează următoarele valori: - -1 dacă valoarea primului parametru este mai mare decât valoarea celui de al doilea parametru; - +1 dacă valoarea primului parametru este mai mică decât valoarea celui de al doilea parametru; - 0 dacă cele două valori sunt egale; În funcţie de valoarea returnată, se vor utiliza pointerii spre stânga sau spre dreapta în operaţia de identificare a nodului copil care urmează să fie procesat. În cazul nostru, funcţia este utilizată astfel: - dacă valoarea nodului părinte este mai mare decât valoarea nodului copil, parcurgerea arborelui, respectiv inserarea nodului frunză, se va face spre stânga; - dacă valoarea nodului părinte este mai mică decât valoarea nodului copil, parcurgerea arborelui, respectiv inserarea nodului frunză, se va face spre dreapta; - dacă valorile celor două noduri sunt egale, nu se inserează nici un nod, pentru că un nod de valoarea dată există deja pe această ramură; Inserarea unui nod în arbore Pentru inserarea unui nod în arbore vom implementa următoare funcţie: ANOD* insnod(anod* st, int vl) ANOD *p, *q; p=new ANOD; p->val=vl; p->st=null; p->dr=null; if (st==null) // arbore gol! st=p; else q=st; for(;;) // se insereaza in subarborele sting if(criteriu(q,p)<0) 2

if (q->st==null) q->st=p; break; else q=q->st; // cauta pina ajunge la frunza continue; // se insereaza in subarborele drept if(criteriu(q,p)>0) if (q->dr==null) q->dr=p; break; else q=q->dr; continue; return st; Funcţia primeşte ca şi argumente adresa nodului rădăcină şi valoarea ataşată nodului ce urmează să fie inserat. Ea trebuie să returneze un pointer ANOD* pentru cazul în care se inserează chiar nodul rădăcină (arborele este vid înainte de inserare). Funcţia efectuează următoarele: - creează un nou nod, căruia îi atribuie valoarea primită ca şi argument, iar pointerii st şi dr sunt încărcaţi cu valoarea NULL; - testează dacă arborele vid, declară noul nod ca fiind rădăcină şi îi returnează adresa; - dacă arborele nu este vid, pornind de la rădăcină, se deplasează în arbore respectând criteriul, pentru a ajunge la nodul părinte al nodului nou inserat. Astfel, pentru fiecare nod se execută următoarele: o dacă criteriu()=-1, se face nod current nodul copil stâng al nodului curent; o dacă criteriu()=1, se face nod current nodul copil stâng al nodului curent; o dacă a ajuns la frunză (st sau dr = NULL), inserează noul nod ca şi copil stâng sau ca şi copil drept, în funcţie de valoarea criteriului; - este demn de remarcat modul de implementare a buclelor, prin intermediul instrucţiunilor continue şi break. În timp ce continue sparge doar blocurile if, rămânând în ciclul for, astfel încât de fiecare dată, în funcţie de criteriu, se trece 3

la un nod copil, break, care este apelat când se ajunge la nodul părinte al nodului nou inserat, sparge şi ciclul for, având ca efect terminarea funcţiei. Dacă vom insera în program liniile de mai jos, vom construi un arbore ca în figura 2. radacina=insnod(radacina,); radacina=insnod(radacina,); radacina=insnod(radacina,); radacina=insnod(radacina,4); radacina=insnod(radacina,7); radacina=insnod(radacina,40); Să vedem de ce s-a obţinut această structură: - apelul funcţiei pentru valoarea găseşte arborele 4 7 40 vid. Deci, se creează un nou nod, căruia i se atribuie valoarea, pentru care se fac pointerii spre nodurile Figura 2 copil NULL şi care este declarat nod rădăcină (fig. 3.1); - apelul funcţiei cu valoarea, creează un nou nod, după care pornind de la rădăcină, caută poziţia în care să-l insereze. Cum valoarea nodului este mai mare decât valoarea rădăcinii, criteriu()>0 şi arborele va fi parcurs spre dreapta. Datorită faptului că pointerul dr al nodului rădăcină este NULL, acesta este încărcat cu adresa noului nod, noul nod va fi inserat ca fiu drept al acestuia (fig 3.2); - apelul funcţiei cu valoarea, creează un nou nod, după care pornind de la rădăcină, caută poziţia în care să-l insereze. Cum valoarea nodului este mai mică decât valoarea rădăcinii, criteriu()<0 şi arborele va fi parcurs spre stânga. Datorită faptului că pointerul st al nodului rădăcină este NULL, acesta este încărcat cu adresa noului nod, noul nod va fi inserat ca fiu stâng al acestuia (fig 3.3); - apelul funcţiei cu valoarea 4, creează un nou nod, după care pornind de la rădăcină, caută poziţia în care să-l insereze. Cum valoarea nodului este mai mică decât valoarea rădăcinii, criteriu()<0 şi arborele va fi parcurs spre stânga, trecându-se la nodul cu valoare. În acest nod, din nou criteriu()<0 şi arborele va fi parcurs spre stânga. Datorită faptului că pointerul st al nodului cu valoare este NULL, acesta este încărcat cu adresa noului nod, noul nod va fi inserat ca fiu stâng al nodului de valoare (fig 3.4); - apelul funcţiei cu valoarea 7, creează un nou nod, după care pornind de la rădăcină, caută poziţia în care să-l insereze. Cum valoarea nodului este mai mică decât valoarea rădăcinii, criteriu()<0 şi arborele va fi parcurs spre stânga, trecându-se la nodul cu valoare. În acest nod, criteriu()>0 şi arborele va fi parcurs spre dreapta. Datorită faptului că pointerul dr al nodului cu valoare este NULL, acesta este încărcat cu adresa noului nod, noul nod va fi inserat ca fiu drept al nodului de valoare (fig 3.); - apelul funcţiei cu valoarea 40, creează un nou nod, după care pornind de la rădăcină, caută poziţia în care să-l insereze. Cum valoarea nodului este mai mare decât valoarea rădăcinii, criteriu()>0 şi arborele va fi parcurs spre dreapta, 4

trecându-se la nodul cu valoare. În acest nod, criteriu()>0 şi arborele va fi parcurs spre dreapta. Datorită faptului că pointerul dr al nodului cu valoare este NULL, acesta este încărcat cu adresa noului nod, noul nod va fi inserat ca fiu drept al nodului de valoare (fig 3.6); 1 2 3 4 6 4 4 7 4 7 40 Parcurgerea unui arbore Pentru listarea valorii unui nod se implementează funcţia: void afiseaza(anod* p) printf(" %d ",p->val); Pentru prelucrarea informaţiei conţinută de arbore, sau pentru listarea conţinutului acestuia, trebuire realizată parcurgerea arborelui. Parcurgerea unui arbore se poate face în mai multe moduri, dintre care, trei sunt demne de reţinut: - în preordine înseamnă accesul la rădăcină şi apoi parcurgerea celor doi subarbori ai ei, întâi subarborele stâng, apoi cel drept. Subarborii, care sunt la rândul lor arbori binari, se parcurg în acelaşi mod. Funcţia care implementează parcurgerea în preordine a arborelui şi afişarea conţinutului nodului este: void preord(anod* p) if (p!=null) afiseaza(p); preord(p->st); preord(p->dr); În programul principal se va adăuga linia printf("\n Preordine : "); preord(radacina); Dacă se compilează şi se execută programul, se va obţine rezultatul:

Preordine : 4 7 40 Să verificăm: o se afişează valoarea rădăcinii () şi se parcurge întâi subarborele drept; o se trec la nodul de valoare, care este noua rădăcină pentru subarborele de sub el. Se parcurge subarborele stâng; o noua rădăcină este nodul de valoare 4. Acesta nu mai are nici o frunză, deci, conform algoritmului, se parcurge subarborele drept al subarborelui cu rădăcina. Deci, va fi afişat nodul de valoare 7; o cum acest nod nu are nici o frunză, se parcurge subarborele drept pornind din precedenta rădăcină (nodul de valoare ), deci se trece la nodul de valoare ; o cum acest nod nu are subarbore stâng, se parcurge subarborele drept, trecându-se la nodul de valoare 40; o nu mai există noduri neparcurse, deci algoritmul se opreşte; - în inordine înseamnă întâi parcurgerea subarborelui stâng, apoi accesul la rădăcină şi apoi parcurgerea subarborelui drept. Cei doi subarbori se parcurg în acelaşi mod. Funcţia care implementează parcurgerea în inordine a arborelui şi afişarea conţinutului nodului este: void inord(anod* p) if (p!=null) inord(p->st); afiseaza(p); inord(p->dr); În programul principal se va adăuga linia printf("\n Inordine : "); inord(radacina); Dacă se compilează şi se execută programul, se va obţine rezultatul: Inordine : 4 7 40 Să verificăm: o se porneşte la parcurgerea arborelui stâng, de la cel mai din stânga nod. Acesta este nodul de valoare 4; o se trece la rădpcina subarborelui, deci în cazul nostru la nodul de valoare ; o conform algoritmului, se parcurge subarborele drept al subarborelui. În cazul nostru, se trece la nodul de valoare 7; o cum nu mai există noduri neparcurse în subarbore, se continuă parcurgerea subarborelui stîng. Nodul al cărui copil stâng este nodul de valoare este 6

nodul de valoare. Acesta este noua rădăcină şi fiind chiar rădăcina arborelui, se trece la parcurgerea subarborelui drept al acestuia. o ar urma reluarea parcurgerii subarborelui stâng al subarborelui drept, pornind de la frunza cea mai din stânga. Cum nu există copii stângi pentru nici un nod, se parcurg doar subarborii din dreapta, deci nodurile şi 40; - în postordine înseamnă parcurgerea subarborelui stâng, al subarborelui drept şi apoi accesul la rădăcină. Cei doi subarbori se parcurg în acelaşi mod. Funcţia care implementează parcurgerea în postordine a arborelui şi afişarea conţinutului nodului este: void postord(anod* p) if (p!=null) postord(p->st); postord(p->dr); afiseaza(p); În programul principal se va adăuga linia printf("\n Postordine : "); postord(radacina); Dacă se compilează şi se execută programul, se va obţine rezultatul: Postordine : 4 7 40 Să verificăm: o se parcurge subarborele stâng pornind de la nodul cel mai din stânga, adică 4; o se parcurge subarborele drept al subarborelui, adică nodul 7; o se accesează rădăcina subarborelui, adică nodul ; o se parcurge subarborele drept al părintelui nodului. Cum acesta nu conţine nici un arbore stâng, se parcurge pornind de la nodul cel mai din dreapta, adică 40, ; o se accesează rădăcina celor doi subarbori, adică nodul ; o cum aceasta este rădăcina arborelui, algoritmul se termină; Ştergerea arborelui Ştergerea unui arbore implică parcurgerea arborelui în postordine cu ştergerea fiecărui nod în parte. Vom implementa următoarele funcţii: void sterg(anod* p) if (p!=null) 7

sterg(p->st); sterg(p->dr); delete p; ANOD* stergarb(anod* p) sterg(p); p=null; return p; Dacă în programul principal se vor adăuga liniile printf("\n\n Afisare valoare radacina dupa stergere arborelui: "); afiseaza(radacina); se va obţine rezultatul Afisare valoare radacina dupa stergere arborelui: NULL 8