1 / 35

Corso di Algoritmi e Strutture Dati

Corso di Algoritmi e Strutture Dati. APPUNTI SUL LINGUAGGIO C Esercizi su Alberi. Alberi. Un albero è un insieme di oggetti, chiamati nodi , su cui è definita una relazione binaria G(x,y) – che leggiamo “ x è genitore di y ” – tale che:

aden
Download Presentation

Corso di Algoritmi e Strutture Dati

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C Esercizi su Alberi

  2. Alberi Un albero è un insieme di oggetti, chiamati nodi, su cui è definita una relazione binaria G(x,y)– che leggiamo “x è genitore di y” – tale che: 1. esiste un unico nodo, chiamato radice, che non ha genitori; 2. ogni nodo x diverso dalla radice ha uno ed unico genitore; 3. per ogni nodo x diverso dalla radice esiste un cammino dalla radice a x • Se x è il genitore di y, allora y è un figlio di x. • Un albero binario è un albero in cui ogni nodo ha al massimo due figli.

  3. Terminologia cammino: sequenza di nodi x1, … , xktale che xi è il genitore di xi+1 lunghezza del cammino: k(numero degli archi) antenato e discendente: dato un nodo x di un albero Tcon radice r, qualunque nodo y sul cammino (unico) da r a x è un antenato di x, mentre x è un discendente di y fratelli: nodi che hanno lo stesso genitore sottoalbero: insieme costituito da un nodo x e tutti i suoi discendenti; x è la radice del sottoalbero foglia: nodo senza figli nodo interno: nodo con uno o piu’ figli grado: il numero di figli di un nodo x è il grado di x; Profondita’ o Livello : • La radice ha profondita’ 0 • Se un nodo ha profondita’ k, i suoi figli hanno profondita’ k+1 Altezza dell’albero : massima profondita’ a cui si trova una foglia ovvero numero di archi nel cammino dalla radice alla foglia piu’ profonda

  4. Alberi binari come lista concatenata Un elemento x di una lista è un oggetto con tre campi info[x]campo chiave left[x]puntatore al sottoalbero (figlio) sinistro right[x] puntatore al sottoalbero (figlio) destro Chiamiamo tale lista T

  5. Alberi binari come lista concatenata head[T] head[T]puntatore al primo elemento x della lista (radice) Albero vuoto: head[T] = NIL 1 2 2 NIL 1 NIL NIL 4 NIL 6 NIL NIL 5 NIL NIL

  6. Alberi in C // definizione della struttura nodo typedefstruct elem{ int info; struct elem* left; struct elem* right; } etree; // definizione del puntatore ai nodi dell’albero typedef etree* ptree;

  7. Verificare se un nodo è una foglia isLeaf(x) return x ≠ NIL and left[x] = NIL and right[x] = NIL void isLeaf(ptree x) { return ((x ≠ NULL) && (x->left == NULL) && (x->right == NULL)); }

  8. Notazione parentetica Esiste anche una notazione testuale detta PARENTETICA ( 1 ( 2 ( 4 () () ) ( 5 () () ) ) ( 3 ( 6 () () ) ( 7 () () ) ) ) Un nodo n che non ha figli è rappresentato da ( n () () ) 1 2 3 4 5 6 7

  9. Notazione parentetica Scriviamo in c una funzione per stampare in notazione parentetica un albero binario (senza indentare) void StampaAlberoNonIndentato(ptree t) { if (t == NULL) { printf("()"); return; } printf(“( %d ", t->info); StampaAlbero(t->left); StampaAlbero(t->right); printf(" )"); }

  10. Notazione parentetica • Scriviamo in c una funzione per stampare in notazione parentetica un albero binario (indentando) • come indentare? sul livello i indentiamo con 2i spazi • ogni volta che incontriamo un nodo ci chiediamo • se è una foglia allora stampiamo il valore del nodo senza andare a capo • se non è una foglia allora stampiamo il valore del nodo e andiamo a capo • una volta stampato il valore del nodo richiamiamo la funzione in modo ricorsivo sui sottoalberi sinistro e destro

  11. Notazione parentetica (indetata) void Indenta(int livello) { int i = 0; for (i = 0; i < 2*livello; i++) printf(“ ”); }

  12. Notazione parentetica (indentato) void StampaLivello(ptree t, int livello) { if (t == NULL) { Indenta(livello); printf("() "); return; } Indenta(livello); printf("( "); switch(isLeaf(t)) { case 0: printf("%d\n", t->info); break; case 1: printf("%d", t->info); break; } StampaLivello(t->left, livello + 1); StampaLivello(t->right, livello + 1); Indenta(livello); printf(")\n"); }

  13. Notazione parentetica (indentato) void StampaAlberoIndentato(ptree t) { StampaLivello(t,0); }

  14. Altezza di un albero Massima profondità a cui si trova una foglia ovvero numero di archi nel cammino dalla radice alla foglia più profonda Massimo(a,b) { if a > b then return a else return b } Profondita(T) { if T = NIL then return -1 else s = Profondita(left[T]) d = Profondita(right[T]) return (Massimo(s,d)+1) }

  15. Altezza di un albero int Massimo(int a, int b) { if (a > b) return a; } int Profondita(ptree t) { int s, d; if (t == NULL) return -1; else { s = Profondita(t->left); d = Profondita(t->right); return (Massimo(s, d) + 1); } }

  16. Presenza di un nodo in un Albero Presente(T, elem){ if (T = NULL) then return false else if info[T] = elem then return true else return Presente(left[T],elem) or Presente(right[T], elem) } int Presente(ptree t, int elem){ if (T == NULL) return 0; else if (t->info == elem) return 1; else return (Presente(t->left,elem) || Presente(t->right, elem)); }

  17. Albero crescente Un albero è crescente se: a) è vuoto b) esiste un cammino radice-foglia con valori sempre crescenti Crescente(T) { if T = NIL then return true if left[T] = NIL and right[T]= NIL then return true if left[T] ≠ NIL then if info[T] < info[left[T]] and Crescente(left[T]) then return true if right[T] ≠ NIL then if info[T] < info[right[T]] and Crescente(right[T]) then return true return 0 }

  18. Albero crescente int Crescente(ptree t) { if (t == NULL) return 1; if (t->left == NULL && t->right == NULL) return 1; if (t->left != NULL) { if ((t->info < t->left->info) && Crescente(t->left)) return 1; } if (t->right != NULL) { if ((t->info < t->right->info) && Crescente(t->right)) return 1; } return 0; }

  19. Visite negli alberi 1 2 3 4 5 6 7 • Visita in preordine: Si analizza la radice, poi si visita sottoalbero sinistro e • sottoalbero destro (Es. 1, 2, 4, 5, 3, 6, 7) • Visita in postordine: Si visita prima sottoalbero sinistro, poi destro, e alla fine • la radice (Es. 4, 5, 2, 6, 7, 3, 1) • Visita Simmetrica: Prima visito il figlio sinistro, poi la radice e quindi il figlio • destro (Es. 4, 2, 5, 1, 6, 3, 7) • Per tutte le visite: nel caso in cui l’albero sia vuoto non viene eseguita nessuna • azione

  20. Visita in preordine 1 2 3 4 5 6 7 PREORDER(T) if T ≠ NIL then visita head[T] PREORDER(left[T]) PREORDER(right[T])

  21. Visita in preordine 1 2 3 4 5 6 7 void VisitaPreordine(ptree t) { if (t == NULL) return; printf(“%d “,t->info); VisitaPreordine(t->left); VisitaPreordine(t->right); }

  22. Visita in postordine 1 2 3 4 5 6 7 POSTORDER(T) if T ≠ NIL then POSTORDER(left[T]) POSTORDER(right[T]) visita head[T]

  23. Visita in preordine 1 2 3 4 5 6 7 void VisitaPostordine(ptree t) { if (t == NULL) return; VisitaPostordine(t->left); VisitaPostordine(t->right); printf(“%d “,t->info); }

  24. Visita Simmetrica 1 2 3 4 5 6 7 SIMMETRICA(T) if T ≠ NIL then SIMMETRICA(left[T]) visita head[T] SIMMETRICA(right[T])

  25. Visita in preordine 1 2 3 4 5 6 7 void VisitaSimmetrica(ptree t) { if (t == NULL) return; VisitaSimmetrica(t->left); printf(“%d “,t->info); VisitaSimmetrica(t->right); }

  26. Esercizio Data una lista L i cui nodi contengono valori interi, scrivere le seguenti procedure (pseudo-codice e implementazione in C): • CANC-Val(L,x) che cancella nella lista L il nodo con valore x • CONT-Val(L,x) che conta in L quanti nodi hanno valore x • INS-Val(L,x,y) che inserisce in L un nodo con valore x dopo il nodo esistente in L con valore y (se il nodo con valore y non esiste allora sarà fatto un inserimento in coda)

  27. Cancellazione di un nodo: dato il valore CANC-Val(L,val) if L = NIL then error “la lista è vuota” else if info(head(L)) = val then CANC-Testa(L) else prev <- head(L) cur <- next(prev) while info(cur) ≠ val and cur ≠ NIL do prev <- cur cur <- next(cur) if cur ≠ NIL then next(prev) <- next(cur) else error “non esiste l’elemento”

  28. Cancellazione di un nodo: dato il valore // funzione per cancellare in una lista un nodo con un valore dato void cancellaVal(plist* l, int val){ plist prev,cur; if (*l==NULL) printf(“La Lista è vuota\n"); else if (*l->info == val) cancellaInTesta(l); else { prev = *l; cur=prev->next; while ((cur->info != val) && (cur != NULL)) { prev = cur; cur = cur->next; } if (cur == NULL) printf(“Non esiste l’elemento\n"); else { prev->next=cur->next; free(cur); } } }

  29. Funzione per valutare il numero di nodi con valore val CONT-Val(L,val) cont <- 0 x <- head(L) while x ≠ NIL do if info(x) = val then cont++ x <- next(x) return cont

  30. Funzione per valutare il numero di nodi con valore val int ContaVal(plist l, int val){ int cont = 0; while (l!=NULL) { if (l->info == val) cont++; l = l->next; } return cont; }

  31. Ricerca di un nodo in una lista void funzione(plist l, valore x) l x SEARCH(L,k) if NULL(L) then return NIL else x <- head(L) while x ≠ NIL and info(x) ≠ k do x <- NEXT(x) return x

  32. Ricerca di un nodo in una lista // funzione per cercare in una lista un nodo plist search(plist l, int n){ int test = 0; while ((l!=NULL)&&(!test)) if (l->info == n) test = 1; else l = l->next; return l; }

  33. Inserimento di un nuovo nodo dopo un nodo dato INS-Val(L,x,y) k <- SEARCH(L,y) if k = NIL INS-Coda(L,x) else info(z) <- x next(z) <- next(k) next(k) <- z

  34. Inserimento di un nuovo nodo dopo un nodo dato // funzione per inserire un nodo con valore x void inserisciVal(plist *l, int x, int y) { plist k = Search(*l,y); if (k == NULL) inserisciInCoda(l,x); else { plist z = (plist)malloc(sizeof(elist)); z->info = x; z->next = k->next; k->next = z; } }

  35. Corso di Algoritmi e strutture Dati APPUNTI SUL LINGUAGGIO C Esercizi su alberi FINE

More Related