Strutture dati: Alberi Laboratorio di Algoritmi e Strutture Dati Ingegneria e Scienze Informatiche - Cesena A.A. 2014-2015 Pietro Di Lena [email protected] Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati Strutture dati: Alberi Definizione Operazioni basilari su Alberi Stampa di una struttura Albero in ASCII Definizione Definizione di Albero: struttura rappresentata come un grafo completamente connesso in cui ogni coppia di nodi è connessa da un unico percorso. Alcuni esempi di applicazione: Teoria dei giochi: rappresentazione di tutte le possibili partite (o di un sottoinsieme) di un gioco Genalogia: alberi genealogici Biologia: alberi filogenetici (ex. tree of life) Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati Strutture dati: Alberi Definizione Operazioni basilari su Alberi Stampa di una struttura Albero in ASCII Struttura dati Albero: rappresentazione grafica A \ \ A 2 1 3 B C B 2 D C 3 D 1 \ E 1 \ F 2 G 2 \ \ \ \ \ 1 2 E F 2 G Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati Strutture dati: Alberi Definizione Operazioni basilari su Alberi Stampa di una struttura Albero in ASCII Nota: definizione della struttura dati nodo per un albero in c # include < stdlib .h > typedef char int struct struct } NODE ; struct NODE { name ; label ; NODE * brother ; NODE * children ; NODE * node_alloc ( char name , int label ) { NODE * node = ( NODE *) malloc ( sizeof ( NODE ) ) ; if ( node == NULL ) return NULL ; node - > name node - > label node - > brother node - > children return node ; = = = = name ; label ; NULL ; NULL ; } Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati Strutture dati: Alberi Definizione Operazioni basilari su Alberi Stampa di una struttura Albero in ASCII Nota: generazione di un albero random # define BASE 65 /* * Generazione random di un albero random di altezza massima * height . Ogni nodo ha un numero di figli compreso tra 0 e * children . I nodi sono marcati con lettere maiuscole A - Z * ( i nomi sono ripetuti se ci sono p i di 26 nodi ) . * I pesi degli archi sono interi random tra 0 e 9. */ NODE * randtree ( int height , int children ) { static int X =0; if ( height >0) { int i , n ; NODE *T , * tmp ; T = node_alloc ( BASE +X , rand () %10) ; X =( X +1) %26; n = rand () %( children +1) ; for ( i =0; i < n ; i ++) if (( tmp = randtree ( height -1 , children ) ) != NULL ) { tmp - > brother =T - > children ; T - > children = tmp ; } return T ; } else return NULL ; } Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati Strutture dati: Alberi Definizione Operazioni basilari su Alberi Stampa di una struttura Albero in ASCII Operazioni basilari su Alberi: altezza e distruzione di un Albero 1: function Height(T ) 2: if T = NULL then 3: return 0 4: else 5: n←0 6: for c ∈ Children(T ) do 7: n ← Max(n, Heigth(c)) 8: end for 9: return n + 1 10: end if 11: end function 1: function DeleteTree(T ) 2: if T = 6 NULL then 3: for c ∈ Children(T ) do 4: DeleteTree(c) 5: end for 6: Delete(T) 7: end if 8: end function ATTENZIONE: Le istruzioni di visita dei figli di un nodo dipendono dalla struttura utilizzata. L’implementazione in C potrebbe essere un po’ differente da quella presentata nello pseudocodice. In particolare, se si decide di utilizzare la struttura NODE suggerita, i cicli for non sono necessari (tutto può essere calcolato in modo ricorsivo). Qual è il costo computazionale di queste funzioni? Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati Strutture dati: Alberi Definizione Operazioni basilari su Alberi Stampa di una struttura Albero in ASCII Operazioni basilari su Alberi: numero di nodi e numero di foglie 1: function CountNodes(T ) 2: if T = NULL then 3: return 0 4: else 5: n←0 6: for c ∈ Children(T ) do 7: n ← n + CountNodes(c) 8: end for 9: return n + 1 10: end if 11: end function 1: function CountLeaves(T ) 2: if T = NULL then 3: return 0 4: else 5: n←0 6: if Children(T ) = ∅ then 7: n←1 8: else 9: for c ∈ Children(T ) do 10: n ← n + CountLeaves(c) 11: end for 12: end if 13: return n 14: end if 15: end function Valgono le stesse considerazioni fatte in precedenza per la visita dei figli. Qual è il costo computazionale di queste funzioni? Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati Strutture dati: Alberi Definizione Operazioni basilari su Alberi Stampa di una struttura Albero in ASCII Esempio di stampa in ASCII di un Albero Come possiamo stampare su terminale ed in modo graficamente chiaro un Albero? A \ \ A 2 1 3 B C B 2 D C 3 D 1 \ E 1 \ F 2 G 2 \ \ \ \ \ 1 2 E F 2 G A + - B :2 + - C :3 | + - E :1 + - D :1 + - F :2 + - G :2 Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati Strutture dati: Alberi Definizione Operazioni basilari su Alberi Stampa di una struttura Albero in ASCII Nota: stampa di un albero in ascii 1/2 Procedura di stampa principale. Richiede l’implementazione della funzione che calcola l’altezza dell’albero Height(T). # include < stdio .h > # include < stdlib .h > void printtree ( NODE * T ) { if ( T != NULL ) { char * indent =( char *) calloc (2* height ( T ) , sizeof ( char ) ) ; NODE * tmp ; printf ("% c :% d \ n " ,T - > name ,T - > label ) ; for ( tmp =T - > children ; tmp != NULL ; tmp = tmp - > brother ) printtree_rec ( tmp , indent ,0) ; free ( indent ) ; } } Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati Strutture dati: Alberi Definizione Operazioni basilari su Alberi Stampa di una struttura Albero in ASCII Nota: stampa di un albero in ascii 2/2 void printindent ( char * indent , int n ) { int i ; for ( i =0; i < n ; i ++) printf ("% c " , indent [ i ]) ; } void printtree_rec ( NODE *T , char * indent , int n ) { if ( T != NULL ) { NODE * tmp ; printindent ( indent , n ) ; printf ("+ -") ; if (T - > brother == NULL ) // Last children indent [ n ++]= ’ ’; else // More brothers indent [ n ++]= ’| ’; indent [ n ++]= ’ ’; printf ("% c :% d \ n " ,T - > name ,T - > label ) ; for ( tmp =T - > children ; tmp != NULL ; tmp = tmp - > brother ) printtree_rec ( tmp , indent , n ) ; } } Pietro Di Lena Laboratorio di Algoritmi e Strutture Dati