La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

ALBERI BILANCIATI Ricordiamo che un albero si dice bilanciato se il livello di tutte le foglie è uguale allaltezza dellalbero o a questa stessa altezza.

Presentazioni simili


Presentazione sul tema: "ALBERI BILANCIATI Ricordiamo che un albero si dice bilanciato se il livello di tutte le foglie è uguale allaltezza dellalbero o a questa stessa altezza."— Transcript della presentazione:

1

2 ALBERI BILANCIATI Ricordiamo che un albero si dice bilanciato se il livello di tutte le foglie è uguale allaltezza dellalbero o a questa stessa altezza meno 1. Dato ad esempio, un albero BST di interi non bilanciato, si attraversa lalbero secondo la procedura IN-ORDER, e per ogni chiave letta: Si inserisce la chiave in un vettore; Al termine del processo il vettore risulta ordinato in maniera crescente; Si leggono i dati del vettore come per una ricerca binaria, dividendolo in sottovettori e inserendo i valori via via letti in un albero BST che risulterà ordinato e bilanciato.

3 // MAIN int main () { Tnodo Bilanciato,A1; int V[40]; RTnodo Nodo; CreaAlbero(A1); writeTree(A1,1);cout<

4

5 void DaAlberoAVettore(Tnodo A, int V[], int &max) { int i; if (A!=NULL) { DaAlberoAVettore(A->left, V, max); V[max]=A->key; max=max+1; DaAlberoAVettore(A->right, V, max); } DaAlberoAVettore(A1, V, vmax); Bilanciato=vet2alb(V, 0,vmax-1); writeTree(Bilanciato,1);cout<

6 Tnodo vet2alb(int Vx[], int i,int j) {int k; if (i>j) return NULL; else if (i==j) return UnisciAlberi(Vx[i],NULL,NULL); else { k=(i+j)/2; return UnisciAlberi(Vx[k],vet2alb(Vx,i,k-1),vet2alb(Vx,k+1,j)); } Tnodo UnisciAlberi(int e,Tnodo a, Tnodo b) { Tnodo c; c=new RTnodo; c->left=a; c->right=b; c->key=e; return c; } DaAlberoAVettore(A1, V, vmax); Bilanciato=vet2alb(V, 0,vmax-1); writeTree(Bilanciato,1);cout<

7 int ControlloBilanciamento(Tnodo A) //supponiamo un max=10000 e min=0 {int cmaxx,cmin; cmaxx=0; cmin=10000; cammino(A,0,cmaxx,cmin); return (cmaxx-cmin); } void cammino(Tnodo A, int livello, int &cmax, int &cmin) { if (A!=NULL) { if ((A->right==NULL)|| (A->left==NULL)) { if (cmaxlivello) cmin=livello; } cammino(A->right,livello+1,cmax,cmin); cammino(A->left,livello+1,cmax,cmin); } else return ; } DaAlberoAVettore(A1, V, vmax); Bilanciato=vet2alb(V, 0,vmax-1); writeTree(Bilanciato,1);cout<

8 Lanimazione che segue mostra come opera lalgoritmo prima descritto e successivamente viene mostrato un suo output.

9 UnisciAlberi(Vx[K],vet2alb(Vx,I,K-1),vet2alb(vx,K+1,j)) gfedcba Vet2ALb(V,1,Vmax); Vet2ALb(V,1,7); K=4 UnisciAlberi(Vx[4],vet2alb(Vx,1,3),vet2alb(vx, 5,7)) Vet2ALb(V,1,3); K=2 UnisciAlberi(Vx[2],vet2alb(Vx,1,1),vet2alb(vx, 3,3)) Vet2ALb(V,1,1); K=1Vet2ALb(V,3,3); K=3 ac b UnisciAlberi(Vx[4],vet2alb(Vx,1,3),vet2alb(vx, 6,7)) Vet2ALb(V,5,7); K=6 Vet2ALb(V,5,5); K=5Vet2ALb(V,7,7); K=7 eg f d d f egca b Tnodo vet2alb(int Vx[], int i,int j) {int k; if (i>j) return NULL; else if (i==j) return UnisciAlberi(Vx[i],NULL,NULL); else { k=(i+j)/2; return UnisciAlberi(Vx[k],vet2alb(Vx,i,k-1),vet2alb(Vx,k+1,j)); } } Tnodo UnisciAlberi(int e,Tnodo a, Tnodo b) {Tnodo c; c=new RTnodo; c->left=a; c->right=b; c->key=e; return c; }

10 Tnodo vet2alb(int Vx[], int i,int j) {int k; if (i>j) return NULL; else if (i==j) return UnisciAlberi(Vx[i],NULL,NULL); else { k=(i+j)/2; return UnisciAlberi(Vx[k],vet2alb(Vx,i,k-1),vet2alb(Vx,k+1,j)); } } albBilanciato

11 GENERAZIONE DI ALBERI CASUALI NON ORDINATI Per generare un albero con chiavi casuali e non ordinato è sufficiente utilizzare una funzione rand() per ottenere chiavi casuali e inserire queste chiavi una volta a destra e una volta a sinistra nellalbero, come mostrato dal codice che segue.

12 Tnodo AlberoCasuale(int n) { // Dato un intero n restituisce un albero di interi di altezza n NON ORDINATO if (n==0) return Insert(rand()%100,NULL,NULL); else return Insert(rand()%100,AlberoCasuale(n-1),AlberoCasuale(n-1)); } GENERAZIONE DI ALBERI CASUALI NON ORDINATI Tnodo Insert(int info1, Tnodo As, Tnodo Ad) { // PER INSERIRE UNA FOGLIA SI CHIAMA CON Insert(Numero,NULL,NULL) Tnodo A2; A2= new Tnodo; A2->inf=info1; A2->ps=As; A2->ps=Ad; return A2; } alberiNonOrdinati

13 Verificare se due alberi sono isomorfi Due alberi binari ordinati si dicono isomorfi solo se sono identici, cioè le radici sono uguali, i rispettivi sottoalberi sinistri sono identici ed i rispettivi sottoalberi destri sono identici.

14 Per gli alberi non ordinati, è del tutto indifferente se una chiave è presente nel sottoalbero destro o nel sottoalbero sinistro della radice. Pertanto due alberi non ordinati sono isomorfi se le loro radici contengono lo stesso elemento ed inoltre o accade che i due sottoalberi sinistri ed i due sottoalberi destri sono isomorfi tra loro oppure accade che il sottoalbero sinistro del primo sia isomorfo al sottoalbero destro del secondo ed il sottoalbero destro del primo è isomorfo al sottoalbero sinistro del secondo. Una procedura ricorsiva, che sfrutta questa definizione permette di verificare se due alberi A e B, non ordinati, sono isomorfi tra di loro.

15 bool uguale(Tnodo A, Tnodo B) { // VERIFICA SE DUE ALBERI SONO ISOMORFI if (A==NULL || B==NULL) return (A==NULL) && (B==NULL); // due alberi sono uguali se sono entrambi NULL else return (A->key==B->key) && uguale(A->left,B->left) && uguale(A->right,B->right); } Allegato: albIsomorf

16 bool cerca(Tnodo A1, Tnodo B1) { // CERCA SE IN A C'E' LA CHIAVE DELLA ROOT DI B // SE LA TROVA VERIFICA CHE I DUE SOTTO ALBERI SONO UGUALI if (A1!=NULL) { if ((A1->key)==(B1->key)) { if (uguale(A1,B1)==true) return true;} else { if (A1->key>B1->key) return cerca(A1->left,B1); else return cerca(A1->right,B1); } } else return false; } ESERCIZIO Siano A e B due alberi BST verificare se B è un sottoalbero di A. albsub

17 In generale se si vogliono contare i nodi di un albero contenenti un elemento che soddisfa una proprietà data P si adotta il seguente schema per la funzione conta: if (A==NULL) return 0; else if (A->key soddisfa P) k=1 else k=0 return k +conta(A->left)+conta(A->right) dove lespressione booleana in parentesi nei casi in cui P sia una proprietà difficile da verificare può diventare una funzione booleana che verifica se A->key gode o meno della proprietà. CONTARE I NODI DI UN ALBERO

18 ESERCIZIO Sia assegnato un albero binario, scrivere un algoritmo tale che sposti ogni figlio sinistro nel corrispondente figlio destro e viceversa. A BC DEF GH A CB DFE HG

19 void ScambiaNodi(Tnodo Tree) {Tnodo Temp; if (Tree != NULL) { ScambiaNodi(Tree->left); ScambiaNodi(Tree->right); Temp=Tree->left; Tree->left= Tree->right; Tree->right=Temp; }; post-order albvari

20 ESERCIZIO LA FAMIGLIA {calcola le parentele } Supponiamo di avere una famiglia tale che ogni suo membro ha al più due figli. Descritte le parentele secondo un albero non ordinato scrivere le funzioni char Padre {dato un nome determinare se ha un padre e chi è} void Figlio {dato un nome determinare se ha uno o due figli e chi sono} char Nonno {dato un nome determinare chi è il nonno}

21 char Fratello {dato un nome determinare se ha un fratello e chi è} char Cugino {dato un nome determinare se ha un Cugino e chi è} figlio padre nonno zio cugino

22 Di seguito si mostra lo pseudo-codice che risolve il problema dellalbero genealogico.

23 Cerca(A, Candidate, Pcand, Pparent) Cerca(A, figlio, Pfiglio, Ppadre) Ppadre->key padre Cerca(A, Ppadre->key, Ppadre, Pnonno) Ppadre ->left ->key|| Ppadre ->right ->key figlio Cerca(A, Ppadre->key, Ppadre, Pnonno) Pnonno ->left ->key Pnonno ->right ->key zio Cerca(A, Ppadre->key, Ppadre, Pnonno) (Pnonno ->left ->left ->key Pnonno ->left ->right ->key)|| (Pnonno -> right ->left ->key Pnonno -> right ->right ->key)|| cugino figlio padre nonno zio cugino Cerca(A, Ppadre->key, Ppadre, Pnonno) Pnonno ->key nonno 9

24 ALBERO GENEALOGICO Assegnato un albero A trovare rispettivamente il padre di un assegnato figlio, il figlio di un assegnato padre, il nonno di un assegnato nipote, lo zio di un assegnato nipote, // MAIN cerca_il_padre(A); cerca_il_figlio(A); cerca_il_nonno(A); cerca_lo_zio(A); void cerca_il_padre(Tnodo Tree) {int figlio; Tnodo Candidato=NULL;Tnodo Padre; cout >figlio; Cerca( Tree, figlio, Candidato, Padre); if (Candidato==NULL) cout<<" Il figlio non c'e'"<

25 ALBERO GENEALOGICO void cerca_il_figlio(Tnodo Tree) {int padre; Tnodo Candidato,Padre; cout >padre; Cerca( Tree, padre, Candidato, Padre); if (Candidato==NULL)cout<<" Il padre non c'e' "<left==NULL)&&(Candidato->right==NULL)) cout<<" Non ha figli "<left!=NULL) cout left->key<right!=NULL) cout right->key<

26 void cerca_lo_zio(Tnodo Tree) {int figlio; Tnodo Candidato,Padre,Nonno; cout >figlio; Cerca( Tree, figlio, Candidato, Padre); if (Candidato==NULL) cout<<" Il figlio non c'e'"<key, Candidato, Nonno); if (Nonno==NULL) cout<<" il padre e' orfano"<left==NULL)&&(Nonno->right==Padre)) cout<left!=NULL)&&(Nonno->left!=Padre)) cout left->key;} if ((Nonno->right!=NULL)&&(Nonno->right!=Padre)) cout right->key;} }

27 void cerca_il_nonno(Tnodo Tree) {int figlio; Tnodo Candidato,Padre,Nonno; cout >figlio; Cerca( Tree, figlio, Candidato, Padre); if (Candidato==NULL) cout<<" Il figlio non c'e'"<key, Candidato, Nonno); if (Nonno==NULL) cout<<" il padre e' orfano"<

28 Scrivere una procedura tale che assegnato un albero binario non ordinato di interi positivi restituisca un puntatore al valore massimo e indichi quante volte questo valore massimo è contenuto nell'albero. void CercaMax(Tnodo ANonOrd, int &Max, int &Cont) { if (ANonOrd!=NULL) { CercaMax(ANonOrd->left,Max,Cont); if (ANonOrd->key>Max) { Max=ANonOrd->key; Cont=1; } else if (ANonOrd->key==Max) Cont=Cont+1; CercaMax(ANonOrd->right,Max,Cont); } Allegato: alb non ordinati ESERCIZIO

29 // Scrivere una procedura che assegnato un albero binario di interi //positivi non ordinato e due numeri positivi N1 e N2 restituisca la // quantità di numeri pari compresi tra N1 e N2. void Elab_Albero(Tnodo ANonOrd,int N1a, int N2a, int & Cont) { if (ANonOrd!=NULL) { Elab_Albero(ANonOrd->left, N1a,N2a,Cont); if ((ANonOrd->key%2==0)&&(ANonOrd->key>N1a)&&(ANonOrd->keyright, N1a,N2a,Cont); } alb non ordinati ESERCIZIO

30 ESERCIZI Verificare se un albero A contiene almeno uno zero. Verificare se lalbero A contiene solo zeri.

31 Verificare se un albero A contiene almeno uno zero. bool unozero(Pnodo A) { if(A==NULL)return false; else if A->key =0 return true; else return ((unozero(A->left) || (unozero(A->right) ); } Verificare se lalbero A contiene solo zeri. bool tuttizero(Pnodo A) { if(A==NULL) return true; else if (A-> key!=0) return false; else return(tuttizero(A->left) && tuttizero(A-> right) ); }

32 ESERCIZIO Sviluppare una funzione che, assegnato un nodo T di un albero binario, restituisce il puntatore al nodo "Zio di T se esiste, NULL altrimenti (nodo "zio" è quel nodo che è figlio dello stesso genitore del nodo T).

33 ESERCIZIO Dati due alberi non ordinati verificare che ordinatamente tutte le chiavi dell'albero A sono multipli delle chiavi dell'albero B. Allegato: alberimultipli

34 ESERCIZIO 1- Scrivere un algoritmo che dato un albero binario scriva le chiavi in ordine prima crescente e poi decrescente. 2- Assegnato un albero BST di numeri interi, fornire una procedura ricorsiva che dica quanti nodi, la cui chiave è un numero dispari, hanno sottoalbero destro nullo. 3- Assegnato un albero non ordinato di interi scrivere una procedura ricorsiva che trasformi l'albero non ordinato in un albero BST. Determinare l'altezza dell'albero non ordinato e dell'albero BST. 4 -Dato un albero binario calcolare quanti nodi hanno il sottoalbero sinistro nullo.

35 ESERCIZIO Sia A un albero binario non ordinato. Ogni qualvolta un nodo dell'albero ha al più un figlio e presenta il campo numero uguale a zero eliminare il nodo sostituendolo con lunico figlio. Esempio:

36 ESERCIZI Dato un albero binario calcolare quanti nodi hanno il sottoalbero sinistro nullo. Dato un albero binario ordinato di interi definire una funzione ricorsiva che restituisca il numero di elementi positivi in esso presenti. Dato un albero BST contare quanti nodi ci sono al di sotto di un nodo preassegnato. Dato un albero BST e la chiave K di un suo nodo determinare il valore della chiave più piccola e di quella più grande del sotto albero di K. Dato un albero non ordinato contare quanti nodi hanno la stessa chiave e quanti figli sono multipli del padre.

37 /* Sviluppare una funzione che, assegnato un albero binario T, conti quanti nodi sinistri, hanno come unico figlio un nodo foglia. */ int contafigli(Tnodo A) { if (A==NULL) return 0; else { if ( ( (A->left!=NULL)&& (A->left->left==NULL)&& (A->left->right==NULL)&& (A->right==NULL) ) { cout key<<" ha come unico figlio un nodo foglia "<left)+contafigli(A->right)+1; } else return contafigli(A->left)+contafigli(A->right); } Albvari A A->right A->left A-> left ->left A-> left -> right


Scaricare ppt "ALBERI BILANCIATI Ricordiamo che un albero si dice bilanciato se il livello di tutte le foglie è uguale allaltezza dellalbero o a questa stessa altezza."

Presentazioni simili


Annunci Google