72
Programarea calculatoarelor - Algoritmi Modul 3 Curs 12-13

an1_sem2_curs12-13_seriaA_2014

Embed Size (px)

DESCRIPTION

e

Citation preview

  • Programarea calculatoarelor -

    Algoritmi

    Modul 3

    Curs 12-13

  • 2

    Cuprins

    1. Arbori

    Introducere

    Arbori binari

    Reprezentarea arborilor binari

    Operaii pe arbori binari

    Parcurgerea arborilor binari

    Abordare obiectual

  • 3

    1. Arbori

    Introducere

    Noiunea de arbore este legat de elemente ale teoriei

    grafurilor i elemente legate ierarhizarea informaiilor, cum ar fi:

    organizarea administrativ

    structurarea unei cri

    ordinea executrii operaiilor la evaluarea expresiilor aritmetice

    Arborii combin avantajele tablourilor (cutri rapide) cu cele ale listelor nlnuite (inserare i tergere rapid)

  • Arborii pot fi definiti in mai multe moduri:

    a) conform teoriei grafurilor, un arbore e considerat

    un graf neorientat, conectat i fr cicluri.

    Numim un graf neorientat o pereche ordonata de

    multimi (X, U), unde:

    -X e o multime finita si nevida de elemente, numite

    noduri sau varfuri

    -U e o multime de perechi neordonate, submultime de

    doua elemente din X, numite muchii.

    G = (X, U) este astfel un graf neorientat avand multimea

    de noduri X si U, multimea de muchii.

    Un graf G e conectat daca pentru doua noduri diferite x

    si y, exista un lant care le leaga.

    Lantul L in G este dat de o succesiune de noduri L = [xi1,

    xi2,, xik] cu proprietatea ca doua noduri consecutive din L sunt adiacente, si:

    4

  • 5

    [xi1, xi2], [xi2, xi3],, [xik-1, xik] U, nodurile xi1 respectiv xik sunt extremitatile lantului, si numarul de muchii ce apar in L defineste

    lungimea lantului. E numit ciclu in G, un lant L pentru care

    xi1=xik, si toate muchiile [xi1, xi2], [xi2, xi3],, [xik-1, xik] sunt diferite doua cate doua.

  • 6

    b) a doua definiie: un arbore cu rdcin este o mulime finit de noduri (n general nevid), n care exist un nod special numit rdcina arborelui r, celelalte noduri fiind grupate n subarbori ai nodului r

    Orice nod este rdcina unui subarbore i orice arbore este sau poate deveni subarbore

    Nodurile conin informaie specific i informaie de legtur spre alte noduri

    Numrul de subarbori nevizi ai unui nod indic gradul nodului respectiv

    Rdcina arborelui este unit cu rdcinile subarborilor prin muchii

  • 7

    Prin prisma acestei definiii arborii sunt date recursive i dinamice (la fel ca listele)

    Definiia anterioar duce la ierarhizarea arborilor pe niveluri:

    nivelul maxim din arbore d nlimea (adncimea arborelui)

    1

    2 4

    6 7

    8

    5

    3

    9

    Nivel : 0

    Nivel : 1

    Nivel : 2

    Nivel : 3 Inaltime: 3

  • 8

    nlimea mai poate fi dat recursiv ca suma:

    1 + maximum(nlimea subarborilor)

    Pentru exprimarea relaiilor ntre noduri se folosesc termeni preluai de la arborii genealogici:

    printe, fiu, frate, strmo, descendent

    Fiecrei muchii i se poate asocia o orientare de la printe la fiu

  • 9

    Orice nod x poate fi atins din rdcin pe un drum unic

    Orice nod care se gsete pe drumul unic de la rdcina r la nodul x se numete ascendent (strmo) al lui x

    Dac y este un ascendent al lui x atunci x este un descendent al lui y

    Toti descendenii unui nod y sunt nodurile din subarborele cu rdcina y

    Un nod ce nu are descendeni se numete nod terminal sau frunz

    Dou noduri care au acelai printe se numesc frai

  • 10

    Operatii

    Vizitarea unui nod: accesarea n scopul executrii unor operaii asupra

    informaiei utile (consultare, afiare,)

    Traversarea unui arbore: vizitarea tuturor nodurilor

    Majoritatea arborilor cu radacina sunt arbori binari (binary trees). n unele aplicatii se folosesc alti arbori cum ar fi arbori de tip quad, hexagonal sau octal

  • 11

    Arbori binari Arbore binar:

    un arbore constituit dintr-un nod rdcin i doi subarbori binari disjunci numii subarborele stng, respectiv subarborele drept (ce pot fi i vizi)

    Fiecare nod are cel mult 2 succesori (fii)

    r

    A1 A2

  • 12

    Rdcina subarborelui stng se numete fiul stng al rdcinii, iar rdcina subarborelui drept se numete fiul drept al rdcinii

    1

    2 3

    5

    6

    4

    7

  • 13

    Clase speciale de arbori binari

    Arbori binari strici :

    orice nod are gradul 0 (nod terminal) sau 2 (doi fii)

    5

    6 7

    1

    2 3

    4

  • 14

    Arbori binari plini:

    au 2k - 1 noduri distincte, plasate pe nivelurile 0,1,...,k-1 a.i. pe fiecare nivel l se gsesc 2l noduri

    1

    2 3

    5 6 4 7

    l = 0

    l = 1

    l = 2

    k = 3

  • 15

    Arbori binari complei:

    se obin dintr-un arbore plin prin eliminarea de la dreapta la stnga a unor noduri de pe ultimul nivel

    pentru a obine un arbore complet cu n noduri:

    se construiete un arbore plin pentru cele n noduri cu 2k+1 - 1 noduri unde n satisface inegalitatea:

    2k

  • 16

    Arbori binari degenerai: au nodurile dispuse pe n niveluri

    toate nodurile, cu excepia ultimului, sunt de ordinul 1 (au un singur descendent direct)

    Observaie: o list poate fi considerat ca un arbore degenerat

    1

    2

    4

    3

    1

    2

    4

    3

  • 17

    Arbori binari echilibrai: pentru orice nod, numrul nodurilor din subarborele

    stng i cel al nodurilor din subarborele drept difer cu cel mult o unitate

    1

    2 3

    4 5

    1

    2 3

    4 5 6

  • 18

    Proprietile arborilor binari

    numrul maxim de noduri pe nivelul l este 2l

    numrul maxim de noduri dintr-un arbore cu nlimea k este 2k+1-1 :

    n orice arbore binar cu n noduri terminale exist (n-1) noduri de grad 2

    un arbore binar cu n noduri are nlimea cel puin egal cu [log2(n)]

    Daca definim prin I lungimea drumurilor interne ca reprezentand suma lungimilor drumurilor de la radacina

    la nodurile nonterminale (interne), cu E suma lungimilor

    drumurilor de la radacina la nodurile terminale (frunze,

    adica externe), atunci un arbore binar cu n noduri interne

    are, E = I + 2n.

  • 19

    Utilizare:

    cel mai adesea pentru reprezentarea unor date caracterizate de o cheie unic:

    cheia este un cmp din informaia specific care este utilizat pentru a identifica nodul respectiv

    dac tipul cheii admite o relaie de ordine (de exemplu mai mic sau mai mare), aceti arbori se pot utiliza pentru cutarea i sortarea eficient a informaiei

  • 20

    Reprezentarea arborilor binari

    Cel mai frecvent se utilizeaz reprezentarea nlnuit cu referine descendente:

    struct ANOD

    {

    // declaratii date; informatii specifice

    void *info;

    struct ANOD *st;

    struct ANOD *dr;

    };

  • 21

    Arbori binari de cutare

    sunt arbori pentru care cheia fiului stng este mai mic dect cea a nodului printe, iar cheia fiului drept este mai mare sau egal cu cea a printelui.

    Daca introducem valorile 200, 100, 150, 125, 400, 80, 60, 90, aceste numere vor fi introduse in arbore

    in felul urmtor:

  • 22

    Urmatorul exemplu genereaz arborele binar prezentat, iar funcia tiparb() care tiprete subarborele stang creat, apoi nodul i apoi subarborele drept (in-order), va duce la ordonarea listei de valori asfel: 60, 80, 90, 100, 125,

    150, 200, 400.

    Exemplu:

    #include

    #include

    #include

    typedef struct anod{

    int nr;

    struct anod *stg;

    struct anod *dr;

    }ANOD;

    void tiparb(ANOD*);

    ANOD* arbore(ANOD*,int);

  • 23

    void main(void){

    ANOD *p=NULL;

    int val=0;

    char ch;

    do

    {

    puts("\nIntrodu nodurile arborelui:");

    scanf("%d",&val);

    p=arbore(p,val);

    puts("Continui introducerea cu y sau Y:");

    ch=getche();

    }while(ch=='y'||ch=='Y') ;

    puts("\nNodurile arborelui creat sunt:");

    tiparb(p);

    }//main

  • 24

    ANOD* arbore(ANOD *x,int y){

    if(x==NULL){

    x=new ANOD; //radacina

    x->nr=y;

    x->stg=NULL;

    x->dr=NULL;}

    else if(x->nr < y) x->dr=arbore(x->dr,y);

    else if(x->nr > y) x->stg=arbore(x->stg,y);

    return x;

    }//arbore

    void tiparb(ANOD* p){

    if(p!=NULL){

    tiparb(p->stg);

    printf("%d\n",p->nr);

    tiparb(p->dr);

    }

    }//tiparb

  • 25

    Operaii pe arbori:

    cutarea unui nod cu o anumit cheie

    inserarea unui nod frunz

    accesul la un nod

    parcurgerea arborelui

    tergerea unui nod, tergerea arborelui

    etc.

    Operaiile de creare, inserare, acces la un nod au la baz un criteriu (nu neaparat de ordonare), care definete locul nodului n arbore, criteriu specific aplicaiei

  • 26

    Se folosesc de obicei dou funcii specifice:

    int criteriu(struct ANOD *p1, struct ANOD *p2);

    ce returneaz:

    -1 : *p2 poate fi un nod al subarborelui stng al

    nodului indicat de p1

    +1 : *p2 poate fi un nod al subarborelui drept al

    nodului indicat de p1

    0 : *p2 nu poate fi un nod al subarborilor nodului

    indicat de p1 (mai exista unul si incrementam un

    contor, frecv)

    Exemplu (pentru un arbore binar de cautare)

    int criteriu(ANOD *p1, ANOD *p2){

    if(p2 ->key< p1 ->key) return -1; // cheia e un numar intreg

    if(p2 ->key > p1 ->key) return 1;

    return 0;

    }//criteriu

  • 27

    n cazul n care funcia criteriu() returneaz valoarea 0 se consider c nodurile sunt echivalente i se apeleaz o alt funcie specific:

    struct ANOD *echivalenta(struct ANOD *p1, struct ANOD *p2);

    nodul indicat de p1 este prelucrat (depinde de aplicaie), iar nodul indicat de p2 este eliminat

    ANOD *echivalenta(ANOD *p1, ANOD *p2) {

    p1 ->frecv++; // prelucrare nod (incrementam nr. de aparitii)

    elibnod(p2);

    return p1;

    }//echivalenta

    Obs: n cazul arborilor binari de cutare aceste funcii nu sunt necesare, deoarece relaia de ordine este simpl

  • 28

    Operaii pe arbori binari

    Pentru simplitate vom considera reprezentarea

    arborelui astfel (informaia util sub forma unui ntreg):

    struct ANOD {

    int info;

    struct ANOD *st;

    struct ANOD *dr;

    };

  • 29

    Cutarea unui nod este cea mai simpl operaie pe arbori, ce

    presupune parcurgerea arborelui i compararea cheii cu valoarea dat

    struct ANOD * CautaNod(int key, struct ANOD *root)

    {

    struct ANOD *current = root;

    while(current->info != key) {

    if(key < current->info)

    current = current->st;

    else

    current = current->dr;

    if(current == NULL)

    return NULL;

    }

    return current;

    }

  • 30

    Inserarea unui nod

    Pentru a realiza inserarea trebuie mai nti gsit locul n care se va insera noul nod

    Aceast cutare se face similar cu cazul anterior, cutarea ncheindu-se atunci cnd s-a ajuns cu nodul curent la valoarea NULL

    Exemplu:

    iniial inserare 6 inserare 10

  • 31

    void InsNod(int key, struct ANOD *root)

    {

    struct ANOD *nNod = new struct ANOD;

    nNod->info = key;

    if(root == NULL) root = nNod;

    else {

    struct ANOD *current = root;

    struct ANOD *parent;

    while(1) {

    parent = curent;

    if(key < current->info) {

    current = current->st;

    if(current == NULL) {

    parent->st = nNod; return;

    }

    }

    else {

    current = current->dr;

    if(current == NULL) {

    parent->dr = nNod; return;

    }

    }

    } // end while

    } // else

    }

  • 32

    tergerea unui nod Este cea mai complicat operaie pentru un arbore

    binar de cutare Pentru tergere trebuie gsit nodul care urmeaz a fi

    ters, dup care apar urmtoarele situaii:

    nodul respectiv este o frunz: se anuleaz referina de la nodul printe ctre nodul n

    cauz

    nodul are un singur fiu: se conecteaz nodul printe la nodul fiu

    nodul are doi fii: trebuie gsit nodul succesor (acel nod care plasat n locul

    nodului ters asigur pstrarea relaiei de ordine ntre noduri)

    nodul de ters se nlocuiete cu: nodul care are cheia cea mai mare n subarborele stng

    sau cu nodul ce are cea mai mic cheie n subarborele drept

    nodul cel mai din stnga al subarborelui drept sau cu nodul cel mai din dreapta al subarborelui stng

  • 33

    Nod de grad 1:

    Nod de grad 2:

  • 34

    int StergeNod(int key, struct ANOD *root)

    {

    struct ANOD *current = root;

    struct ANOD *parent = root;

    int FiuStang;

    // cautare nod

    while(current->info != key) {

    parent = current;

    if(key < current->info) {

    FiuStang = 1;

    current = current->st;

    }

    else {

    FiuStang = 0;

    current = current->dr;

    }

    if(current == NULL)

    return 0;

    }

  • 35

    // nu are fii (frunza)

    if(current->st == NULL && current->dr == NULL)

    {

    if(current = =root) // este chiar radacina

    root = NULL; // se sterge nodul radacina

    else if(FiuStang) // e in subarborele stang

    parent->st = NULL;

    else // e in subarborele drept

    parent->dr = NULL;

    return 1;

    }

  • 36

    Exemplu: nodul care se va sterge este frunza

    if(FiuStang)

    parent->st = NULL; 8

    4 12

    2 6 current

    parent

    st dr

  • 37

    // nod cu un singur fiu

    if(current->dr == NULL) { // nu are fiu drept

    if(current == root) // este radacina

    root = current->st; // fiul stang devine radacina

    else if(FiuStang) // este in subarborele stang

    parent->st = current->st;

    else

    parent->dr = current->st; // este in subarb. drept

    return 1;

    }

    if(current->st == NULL) { // nu are fiu stang

    if(current == root) // este radacina

    root = current->dr; // fiul drept devine radacina

    else if(FiuStang)

    parent->st = current->dr;

    else

    parent->dr = current->dr;

    return 1;

    }

  • 38

    Exemplu: stergere nod cu un singur fiu

    if(!FiuStang)

    parent->dr = current->st;

    12

    10

    current

    parent

    dr dr

    parent

    dr

    current

    parent

    dr

    st

    6 2

    4

    8

  • 39

    // nod cu doi fii

    struct ANOD *succesor = getSuccesor(current);

    if(current == root) // nodul de sters este radacina

    root = succesor; // succesorul devine radacina

    else if(FiuStang) // nodul este in subarborele stang

    parent->st = succesor; // succesorul devine fiu stang

    else

    parent->dr = succesor; // succesorul devine fiu drept

    succesor->st = current->st; // legatura cu fiul stang al nodului sters

    return 1;

    }

  • 40

    1 18

    -3 4 7 21

    19 25

    5

    succesor

    parent

    current

    parent->dr = succesor;

    succesor->st = current->st;

    succesor

  • 41

    struct ANOD *getSuccesor(struct ANOD *p)

    {

    struct ANOD *succParent = p;

    struct ANOD *succ = p;

    struct ANOD *current = p->dr; // cautam in subarborele drept

    while(current != NULL) {

    succParent = succ;

    succ = current;

    current = current->st; // mergem spre stanga (cautam min)

    }

    if(succ != p->dr) {

    succParent->st = succ->dr; (NULL , sterge legatura spre succesor)

    succ->dr = p->dr; // legatura cu subarborele drept

    }

    return succ;

    }

  • 42

    n cazul n care frecvena operaiei de tergere este mic, se poate ataa un indicator (flag) fiecrui nod care s precizeze dac nodul respectiv este ters, iar funciile de vizitare s testeze acest indicator nainte de a lua o decizie

  • 43

    Parcurgerea arborilor binari

    Parcurgerea (traversarea) se face pentru prelucrarea informaiilor pstrate n noduri

    Parcurgerea se face ntr-o anumit ordine, dat de aplicaie

  • 44

    Parcurgerea n lime: se prelucreaz nodul rdcin apoi, de la stnga

    spre dreapta, nodurile aflate pe primul nivel, etc. (exemplu lista personalului cu funcii de conducere);

    pentru parcurgere se poate folosi o coad iniializat cu nodul rdcin; apoi ct timp exist noduri n coad:

    se extrage primul nod din coad

    se prelucreaz nodul extras

    se adaug n coad fiii nodului extras

    Parcurgerea n adncime: fiii unui nod sunt parcuri de la stnga la dreapta dar

    trecerea de la fiul curent la fratele din dreapta se face numai dup ce s-au parcurs toi descendenii fiului curent

  • 45

    Moduri simple de parcurgere pentru arborii binari: n preordine:

    rdcina -> subarbore stng -> subarbore drept

    n inordine: subarbore stng -> rdcina -> subarbore drept (mai

    frecvent utilizat)

    n postordine: subarbore stng -> subarbore drept -> rdcina

    Subarborii sunt parcuri n acelai mod (de la stnga la dreapta)

    Parcurgerile n preordine i n postordine sunt folosite la evaluarea expresiilor algebrice

    n cazul arborilor binari de cutare, parcurgerea n inordine asigur vizitarea nodurilor n ordine cresctoare

  • 46

    // parcurgerea in preordine

    void preord(struct ANOD *p)

    {

    if(p != NULL) {

    prelucrare(p);

    preord(p->st);

    preord(p->dr);

    }

    }

    //parcurgerea in inordine

    void inord(struct ANOD *p)

    {

    if(p != NULL) {

    inord(p->st);

    prelucrare(p);

    inord(p->dr);

    }

    }

  • 47

    // parcurgerea in postordine

    void postord(struct ANOD *p)

    {

    if(p != NULL)

    {

    postord(p->st);

    postord(p->dr);

    prelucrare(p);

    }

    }

  • 48

    // stergerea arborelui

    void sterge_arb(struct ANOD *p)

    {

    if(p != NULL) {

    sterge_arb(p->st);

    sterge_arb(p->dr);

    elib_nod(p); //functie specifica aplicatiei

    }

    }

    // afisarea arborelui

    void afis_arb(struct ANOD *p)

    {

    if(p != NULL) {

    afis_arb(p->st);

    afis_inf_specif(p->inf);

    afis_arb(p->dr);

    }

    }

  • 49

    // initializare arbore

    int init_arb(struct ANOD *rad)

    {

    rad = NULL;

    return 0;

    }

    //verifica daca arborele este vid

    int arbore_vid(struct ANOD *rad)

    {

    return(rad == NULL)

    }

  • 50

    //creaza arbore

    int creaza_arb(void *info, struct ANOD *stt, struct ANOD *drr, struct ANOD *rad)

    {

    rad = new ANOD;

    if(!rad)

    return 1;

    rad -> inf = info;

    rad -> st = stt;

    rad -> dr = drr;

    return 0;

    }

    // modificarea informatiei dintr-un nod

    int modif_inf(struct ANOD *rad, void *x)

    {

    if(rad != NULL)

    rad -> inf = x;

    return (rad != NULL);

    }

  • 51

    // modificarea fiului stang

    int modif_st(struct ANOD *rad, struct ANOD *x)

    {

    if(rad != NULL)

    rad ->st = x;

    return (rad != NULL);

    }

    // modificarea fiului drept

    int modif_dr(struct ANOD *rad, struct ANOD *x)

    {

    if(rad != NULL)

    rad ->dr = x;

    return (rad != NULL);

    }

  • 52

    // verifica daca nodul este frunza

    int frunza(struct ANOD *rad)

    {

    return((rad -> st == NULL) && (rad -> dr == NULL));

    }

    // calculeaza numarul de noduri din arbore

    int nr_noduri(struct ANOD *rad)

    {

    if(rad == NULL)

    return 0;

    return(nr_noduri(rad->st) + nr_noduri(rad->dr) + 1);

    }

  • 53

    // calculeaza inaltimea arborelui

    int inalt_arb(struct ANOD *rad) {

    int hst, hdr;

    if(rad == NULL)

    return 0;

    hst = inalt_arb(rad -> st);

    hdr = inalt_arb(rad -> dr);

    return((hst > hdr ? hst : hdr) + 1);

    }

    // adauga o frunza in subarborele stang

    void adauga_frunza(struct ANOD *nodc, struct ANOD *nodf){

    if(arbore_vid(nodc))

    nodc = nodf;

    else

    adauga_frunza(nodc->st, nodf);

    }

  • 54

    Aplicaie: citete datele de intrare sub forma unor cuvinte distincte

    construiete un arbore binar cu cuvintele n ordine alfabetic

    transmite datele de ieire formate din cuvintele distincte din

    datele de intrare ordonate mpreun cu numrul lor de apariii

    typedef struct anod {

    char *word;

    int count;

    struct anod *left;

    struct anod *right;

    } ANOD;

    void afis_arb(ANOD*);

    ANOD* adauga_arb(ANOD*, char *);

  • 55

    void main(void)

    {

    ANOD *p=NULL;

    char word[32];

    char ch;

    do {

    coutword;

    p=adauga_arb(p,word);

    cout

  • 56

    ANOD *adauga_arb(ANOD *p, char *w)

    {

    int cond;

    if (p == NULL) {

    p = new ANOD;

    p->word = new char [strlen(w)+1];

    strcpy( p->word, w);

    p->count = 1;

    p->left = p->right = NULL;

    }

    else if ((cond = strcmp(w, p->word)) == 0)

    p->count++; /*ajusteaza nr. de aparitii*/

    else if (condleft = adauga_arb(p->left, w);

    else /*adauga nod la dreapta*/

    p->right = adauga_arb(p->right, w);

    return p;

    }

  • 57

    void afis_arb(ANOD* p)

    {

    if(p!=NULL) {

    afis_arb(p->left);

    cout

  • 58

    Abordare obiectual

    enum BOOL {FALSE=0, TRUE=1};

    // clasa nod

    class TNodAB

    {

    public:

    int cheie;

    TNodAB *stg,*dr;

    TNodAB(int k) {

    cheie = k;

    stg = dr =NULL;

    }

    };

  • 59

    // clasa arbore

    class TArboreABO {

    TNodAB *radacina;

    TNodAB *adauga(TNodAB *r, int k);

    TNodAB *elimina(TNodAB *u, TNodAB *q);

    TNodAB *sterge(TNodAB *r, int k);

    int inaltime(TNodAB *r);

    void inordine(TNodAB *r);

    void preordine(TNodAB *r);

    void postordine(TNodAB *r);

    void tipar_arbore(TNodAB *r, int h);

    void distruge(TNodAB *r);

  • 60

    public:

    TArboreABO( );

    ~TArboreABO( );

    void Adauga(int k);

    void Sterge(int k);

    BOOL Prezent(int k);

    int Inaltime( );

    void Inordine( );

    void Preordine( );

    void Postordine( );

    void TiparArbore( );

    };

  • 61

    TArboreABO::TArboreABO( ) {

    radacina = NULL;

    }

    TArboreABO::~TArboreABO( ) {

    distruge(radacina);

    }

    void TArboreABO::distruge(TNodAB *r) {

    if (r) {

    distruge(r->stg);

    distruge(r->dr);

    delete r;

    }

    }

  • 62

    void TArboreABO::Adauga(int k) {

    radacina = adauga(radacina, k);

    }

    TNodAB * TArboreABO::adauga(TNodAB *r, int k) {

    if (!r) {

    r = new TNodAB(k);

    return r;

    }

    else if (k < r->cheie)

    r->stg = adauga(r->stg, k);

    else if (k > r->cheie)

    r->dr = adauga(r->dr, k);

    return r;

    }

  • 63

    int TArboreABO::Inaltime( ) {

    return inaltime(radacina);

    }

    int max(int a, int b) {

    if (a>b)

    return a;

    return b;

    }

    int TArboreABO::inaltime(TNodAB *r) {

    if (!r)

    return 0;

    return

    max(inaltime(r->stg), inaltime(r->dr))+1;

    }

  • 64

    BOOL TArboreABO::Prezent(int k)

    {

    TNodAB *crt=radacina;

    while (crt) {

    if (k == crt->cheie)

    return TRUE;

    if (kcheie)

    crt = crt->stg;

    if (k>crt->cheie)

    crt = crt->dr;

    }

    return FALSE;

    }

  • 65

    TNodAB *TArboreABO::elimina(TNodAB *u, TNodAB *q) {

    // elimina nodul din extrema dreapta

    // si returneaza radacina subarborelui obtinut

    TNodAB *t;

    if(q->dr != NULL)

    q->dr = elimina(u, q->dr);

    else {

    t = q;

    u->cheie = q->cheie;

    q = t->stg;

    delete t;

    }

    return q;

    }

  • 66

    TNodAB * TArboreABO::sterge(TNodAB *r, int k) {

    TNodAB *t;

    if(r != NULL)

    if( k < r->cheie)

    r->stg = sterge(r->stg, k);

    else

    if (k> r->cheie)

    r->dr = sterge(r->dr, k);

    else {

    t = r;

    if (t->stg == NULL) {

    r = t->dr;

    delete t;

    }

    else if (t->dr == NULL) {

    r = t->stg;

    delete t;

    }

    else t->stg = elimina(t, t->stg);

    }

    return r;

    }

  • 67

    void TArboreABO::Sterge(int k) {

    radacina=sterge(radacina, k);

    }

    void TArboreABO::Inordine( ) {

    inordine(radacina);

    }

    void TArboreABO::inordine(TNodAB * r) {

    if (r) {

    inordine(r->stg);

    cout

  • 68

    void TArboreABO::Preordine( ) {

    preordine(radacina);

    }

    void TArboreABO::preordine(TNodAB * r) {

    if (r) {

    cout

  • 69

    void TArboreABO::Postordine( ) {

    postordine(radacina);

    }

    void TArboreABO::postordine(TNodAB * r) {

    if (r) {

    postordine(r->stg);

    postordine(r->dr);

    cout

  • 70

    void TArboreABO::tipar_arbore(TNodAB *r, int h)

    {

    if (r) {

    tipar_arbore(r->stg, h-5);

    for (int i=1; i

  • 71

    void main(void)

    {

    int rn;

    int vmax = 100, vmin = 1;

    srand((unsigned)time(NULL)); TArboreABO *a=new TArboreABO;

    cout

  • 72