Informatica 3 Informatica 3 LEZIONE 17: lberi generici Lezione 17 - Modulo 1 Modulo 1: Definizione e DT Modulo 2: Implementazione Modulo 3: lberi e classi di equivalenza Definizione e DT Politecnico di Milano - Prof. Sara Comai 1 Politecnico di Milano - Prof. Sara Comai 2 Introduzione lbero generico Definizione di albero T: insieme finito di uno o più nodi tali che esiste un nodo R detto radice di T i rimanenti nodi sono partizionati in n>=0 sottoinsiemi disgiunti T 1, T 2,..., T n ognuno dei quali è un albero e le cui radici R 1, R 2,... R n sono figli di R T 1, T 2,..., T n sono sotto-alberi di T i T i sono ordinati: T i viene prima di T j se i<j DT dell albero generico // General tree node DT template <class Elem> class GTNode { public: GTNode(const Elem&); // Constructor ~GTNode(); // Destructor Elem value(); // Return value bool isleaf(); // TRUE if is a leaf GTNode* parent(); // Return parent GTNode* leftmost_child(); // First child GTNode* right_sibling(); // Right sibling void setvalue(elem&); // Set value void insert_first(gtnode<elem>* n); void insert_next(gtnode<elem>* n); void remove_first(); // Remove first child void remove_next(); // Remove sibling ; Grado di uscita di un nodo (out degree): numero di figli del nodo Foresta: collezione di uno o più alberi Politecnico di Milano - Prof. Sara Comai 3 Politecnico di Milano - Prof. Sara Comai 4
DT dell albero generico (2) template <class Elem> class GenTree { private: void printhelp(gtnode*); // Print helper function public: GenTree(); // Constructor ~GenTree(); // Destructor void clear(); // Send nodes to free store GTNode* root(); // Return the root // Combine two subtrees void newroot(elem&, GTNode<Elem>*, GTNode<Elem>*); void print(); // Print a tree ; Politecnico di Milano - Prof. Sara Comai 5 ttraversamento di un albero generico ttraversamenti preordine si visita la radice e poi ogni sotto-albero da sinistra verso destra (VLR) postordine si visitano prima i sotto-alberi da sinistra verso destra e poi la radice (LRV) in ordine non definito template <class Elem> void GenTree<Elem>:: preorder(gtnode<elem>* subroot) { if (subroot->isleaf()) cout << "Leaf: "; else cout << "Internal: "; cout << subroot->value() << "\n"; for (GTNode<Elem>* temp = subroot->leftmost_child(); temp!= NULL; temp = temp->right_sibling()) preorder(temp); RCDEBF Politecnico di Milano - Prof. Sara Comai 6 Informatica 3 Lezione 17 - Modulo 2 Implementazione con lista dei figli Implementazione con lista dei figli ogni nodo viene rappresentato in un array e contiene i dati, il puntatore al padre ed un puntatore alla lista dei figli, memorizzati da sinistra verso destra indice dato padre Implementazione Politecnico di Milano - Prof. Sara Comai 7 immediato: trovare figlio di sinistra non immediato: trovare fratello di destra combinare alberi se sono memorizzati in array differenti Politecnico di Milano - Prof. Sara Comai 8
Implementazione con figlio di sinistra e fratello di destra (1) Implementazione con figlio di sinistra e fratello di destra ogni nodo viene rappresentato in un array e contiene i dati, il puntatore al padre, al primo figlio di sinistra e al fratello di destra Implementazione con figlio di sinistra e fratello di destra (2) combinazione di due alberi sx dato padre dx sx dato padre dx risolve i problemi dell implementazione tramite lista ai figli richiede meno spazio per ogni nodo è necessaria una quantità costante di spazio Politecnico di Milano - Prof. Sara Comai 9 Politecnico di Milano - Prof. Sara Comai 10 Implementazione con nodi dinamici (1) Implementazione con nodi dinamici ogni nodo viene rappresentato in un array e contiene i dati, il numero dei figli e i puntatori ai figli array di puntatori ai figli come parte del nodo il numero di figli deve essere noto quando si crea il nodo e funziona bene se non cambia dinamicamente implementare un garbage collector oppure un gestore della memoria dato #figli Implementazione con nodi dinamici (2) lista concatenata dei puntatori ai figli più flessibile ma richiede più spazio Politecnico di Milano - Prof. Sara Comai 11 Politecnico di Milano - Prof. Sara Comai 12
Implementazione dinamica con figlio di sinistra e fratello di destra Si noti che l implementazione con figlio di sinistra e fratello di destra è un albero binario da un albero generico è possibile passare ad un albero binario in cui il figlio di sinistra rappresenta il primo nodo figlio dell albero generico e il nodo di destra rappresenta il fratello di destra dell albero generico lo si può applicare anche a foreste di nodi in cui le radici sono considerate come fratelli radice lberi N-ari lbero N-ario: albero i cui nodi hanno tutti N figli 2 figli: albero binario 4 figli: PR quadtree Si implementano in modo simile agli alberi binari all aumentare di N il numero di puntatori NULL rischia di aumentare preferire un implementazione in cui i nodi interni e le foglie vengono tenute distinte Politecnico di Milano - Prof. Sara Comai 13 Politecnico di Milano - Prof. Sara Comai 14 Implementazione sequenziale (1) Scopo: memorizzare i valori di una serie di nodi con l informazione minima per ricostruire la struttura dell albero implementazione sequenziale vantaggio: risparmia spazio perchè non memorizza i puntatori svantaggio: l accesso ad un nodo richiede l accesso ai nodi che lo precedono nella sequenza - non è più Θ(log n) Serializzazione di una struttura ad albero: oggetto memorizzato come sequenza di byte Implementazione sequenziale (2) Implementazione: i valori dei nodi vengono memorizzati come enumerazione di un attraversamento in preordine si memorizzano informazioni sulla struttura lbero binario: si elenca ogni valore del nodo i nodi non vuoti vengono trattati come nodi interni con due figli (che possono essere vuoti) solo i valori NULL vengono trattati come foglie B/D//CEG///FH//I// Politecnico di Milano - Prof. Sara Comai 15 Politecnico di Milano - Prof. Sara Comai 16
Implementazione sequenziale (3) lberi binari pieni si marcano i nodi come interni ( ) o foglia Se un nodo è interno allora ha due figli Se è foglia allora il nodo successivo è il figlio di destra di un antenato B /DC E G/F HI Implementazione sequenziale (4) lberi generici occorre tener traccia del numero di figli in alternativa: indicare quando termina la lista dei figli ) indica che è una foglia un ulteriore ) che è anche l ultimo figlio del padre RC)D)E))BF))) foglia ultimo figlio di B ultimo figlio di R Politecnico di Milano - Prof. Sara Comai 17 Politecnico di Milano - Prof. Sara Comai 18 Informatica 3 Lezione 17 - Modulo 3 Implementazione Implementazione con puntatore al padre per ogni nodo si memorizza solamente il puntatore al padre dati due nodi, appartengono allo stesso albero? --> FIND merging di due alberi --> UNION dato un nodo qual è il figlio più a sinistra? ed il fratello? KO lberi e classi di equivalenza indice del padre dato indice del nodo Politecnico di Milano - Prof. Sara Comai 19 Politecnico di Milano - Prof. Sara Comai 20
Implementazione (2) // Return TRUE if nodes in different trees bool Gentree::differ(int a, int b) { int root1 = FIND(a); // Find root for a int root2 = FIND(b); // Find root for b return root1!= root2; // Compare roots // Return the root node int Gentree::FIND(int curr) const { while (array[curr]!=root) curr = array[curr]; return curr; // t root void Gentree::UNION(int a, int b) { int root1 = FIND(a); // Find root for a int root2 = FIND(b); // Find root for b if (root1!= root2) array[root2] = root1; Problema delle classi di equivalenza Problema: assegnare gli elementi di un insieme a delle classi equivalenza rappresentate da insiemi disgiunti B D C H E I J Politecnico di Milano - Prof. Sara Comai 21 Politecnico di Milano - Prof. Sara Comai 22 Problema delle classi di equivalenza Problema: assegnare gli elementi di un insieme a delle classi equivalenza rappresentate da insiemi disgiunti I lgoritmo Input: insieme di elementi da assegnare alle classi di equivalenza insieme di coppie di equivalenza B D C H E J Esempio elementi = {, B, C, D, E, F, G, H, I, J, coppie di equivalenza = { (,B), (C,H), (G,F), (D,E), (I.F), (,H), (E,G), (H,E) classi di equivalenza Politecnico di Milano - Prof. Sara Comai 23 Politecnico di Milano - Prof. Sara Comai 24
lgoritmo (2) Regola della union pesata Per avere un algoritmo efficiente: mantenere bassa l altezza dell albero Regola della union pesata: fare l unione di due alberi inserendo l albero con il minor numero di nodi come figlio dell albero con più nodi Profondità: Θ(log n) deriva dal fato che: profondità dell albero più piccolo si incrementa di 1 profondità dell albero più grande = profondità del nodo più profondo dei due alberi (+ 1 se il nodo più profondo si trova nell albero più piccolo) totale nodi >= 2 * numero dei nodi dell albero più piccolo Politecnico di Milano - Prof. Sara Comai 25 Politecnico di Milano - Prof. Sara Comai 26 Compressione del percorso int Gentree::FIND(int curr) const { if (array[curr] == ROOT) return curr; return array[curr] = FIND(array[curr]); Politecnico di Milano - Prof. Sara Comai 27