Corso di Informatica 2 a.a. 2003/04 Lezione 6 Alberi binari Corso di Informatica 2 a.a. 2003/04 Lezione 6 Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Cosa sono gli alberi? Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Strutture gerarchiche di ogni tipo Generale Colonnello1 Maggiore1,1 Maggiore1,m Colonnellok Maggiorek,1 Maggiorek,n Capitano Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Strutture gerarchiche di ogni tipo Strutture dati Tipi di dato e strutture dati Specifica e realizzazione Rappresentazione in memoria Liste L’ADT delle liste Realizzazione con vettori Realizzazione con puntatori Pile e code L’ADT delle pile … Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Definizioni Un albero èun grafo connesso aciclico; nel caso finito può essere definito induttivamente come un insieme tale che: è un albero; se k 0, T1, …, Tk sono alberi, v un vertice, allora {v, T1, …, Tk } è un albero Un insieme di alberi è una foresta. albero grafo ciclico foresta Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Struttura induttiva degli alberi nodo albero albero Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Alberi con radice e foglie La radice è un nodo privilegiato di un albero; se l’albero è un grafo non orientato qualunque nodo può considerarsi radice; se l’albero è orientato allora due casi: la radice ha solo archi in uscita (albero sorgente) la radice ha solo archi in entrata (albero pozzo) Una foglia è un nodo da cui non esce alcun arco Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Alberi sorgente, alberi pozzo Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
f è un discendente di a; a è un avo di f Parentele a è padre di b e c a b è figlio di a c b f è un discendente di a; a è un avo di f d e f d è fratello di e Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Un cammino dalla radice ad una foglia si dice ramo Cammini Cammino: sequenza di archi ciascuno incidente sul vertice di quello successivo Un cammino dalla radice ad una foglia si dice ramo Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Livelli Livello: insieme di vertici equidistanti dalla radice L’altezza è la massima distanza dalla radice di un livello non vuoto Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Alberi ordinati Un albero è ordinato quando lo sono (linearmente) i suoi livelli Come alberi ordinati siamo diversi a a b c d = c b d Conta solo l’ordine, non sinistra e destra Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Alberi k-ari Arietà = massimo num. dei figli di qualche nodo Io sono un albero ternario Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Alberi posizionali Un albero ordinato è posizionale quando nell’ordine dei livelli si tiene conto di (si deve quindi fissare l’arietà) a a b c d b c d Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Una specifica Sintassi Tipi: Tree, Node Operatori: NewTree: void Tree IsEmptyTree: Tree boolean InsAsRoot: Node, Tree Tree Root: Tree Node Parent: Node, Tree Node Leaf: Node, Tree boolean … Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Una specifica Sintassi Tipi: Tree, Node Operatori: … Child: Node, Tree Node HasSibling: Node, Tree Boolean Sibling: Node, Tree Node InsTree: Node, Node, Tree, Tree Tree DelTree: Node, Tree Tree Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Semantica degli operatori Con qualcosa si deve pur cominciare A cosa servono queste banalità? r InsAsRoot(r, ) InsAsRoot(n, T ) = T Pre: T = Post: T è l’albero il cui unico nodo è n Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Semantica degli operatori b c d T r b DelTree(a, T ) DelTree(n, T ) = T Pre: n è un nodo di T Post: T risulta da T eliminando il sottoalbero con radice in n Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Semantica degli operatori b c d z x v InsTree(c, a, T, U ) r a b c d T z x v U InsTree(n, m, T, U ) = T Pre: m, n sono nodi di T, U Post: T risulta da T inserendo U come figlio di m e fratello successivo di n se n m primo figlio di m se n = m Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Semantica degli operatori b c d z x v InsTree(a, a, T, U ) r a b c d T z x v U InsTree(n, m, T, U ) = T Pre: m, n sono nodi di T, U Post: T risulta da T inserendo U come figlio di m e fratello successivo di n se n m primo figlio di m se n = m Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Semantica degli operatori NewTree () = (albero vuoto) Root(T) = la radice di T Parent (n, T) = m Pre: n T Post: m padre di n Child (n, T) = m Pre: n T, Leaf(n, T) = false Post: m è il primo figlio di n Sibling (n, T) = m Pre: n T , HasSibling (n, T) = true Post: m è il fratello successivo di n IsEmptyTree(T) = true se T = , false altr. Leaf(n, T) = b Pre: n T , b = true sse n è una foglia HasSibling(n, T) = b Pre: n T Post: b = true sse n ha un fratello Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Realizzazioni: vettore dei padri Efficiente per rappresentare alberi pozzo di cardinalità (numero dei nodi) fissata c b f d e etichetta del nodo indice del nodo indice del padre a 1 b 2 c 3 d 4 e 5 f 6 Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Alberi binari: definizione induttiva L’insieme degli alberi binari etichettati in A, BT(A), è definito induttivamente: BT(A) (albero vuoto) a A, l BT(A), r BT(A) ConsTree(a, l, r) BT(A) Si introduce la nozione di sottoalbero sinistro e destro a l r Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Alberi binari realizzati con puntatori d T info left right r a b c d T Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Codifica binaria di alberi k-ari g a b c d e f g Nel caso di alberi non ordinati la codifica non è univoca! Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Realizzazioni: con puntatori b c d e f g info child sibling parent a b c d e f g Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
La cardinalità di un albero binario Right(B) = r Left(B) = l Cardinalità (B) if B = then return 0 else return 1 + Cardinalità (Left(B)) + Cardinalità (Right(B)) Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
L’altezza di un albero binario Si usa una funzione ausiliaria perché il caso di base B = è essenziale alla ricorsione Altezza (B) // Pre: B // Post: ritorna l’altezza di B return Altezza_aux (B) Altezza_aux (B) // Post: ritorna l’altezza di B, 0 se B = if B = then return 0 else return max{Altezza_aux(Left(B), Altezza_aux(Right(B)) + 1 Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
La ricorsione sugli alberi ContaFoglie (T) // Post: ritorna il numero delle foglie di T if T = then return 0 due casi di base else if T ha un solo nodo then return 1 else siano T1, …, Tk i sottoalberi con radici nei nodi figli di della radice di T return Questo pseudocodice è lontano dalla realizzazione Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
La ricorsione sugli alberi ContaFoglie (T) // Post: ritorna il numero delle foglie di T if IsEmptyTree(T) then return 0 else return Cf_aux(Root(T), T) Cf_aux (n, T) // Pre: n T // Post: ritorna il numero delle foglie del sottoalbero di T con radice in n Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
La ricorsione sugli alberi Cf_aux (n, T) // Pre: n T // Post: ritorna il numero delle foglie del sottoalbero di T con radice in n if Leaf(n, T) then return 1 else // n ha almeno un figlio in T m Child(n, T) foglie Cf_aux (m, T) while HasSibling (m, T) do m Sibling (m, T) foglie foglie + Cf_aux (m, T) return foglie Se m aveva un fratello, allora l’attuale valore di m è un nodo di T Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Visite: Depth First Search DFS (T) // Post: visita i nodi di T in profondità if T then visita Root(T) siano T1, …, Tk i sottoalberi con radici nei nodi figli di della radice di T for i 1 to k do DFS (Ti) Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Visite: Depth First Search DFS (T) // Post: visita i nodi di T in profondità if not IsEmtyTree(T ) then DFS_aux (Root(T), T) DFS_aux (n, T) // Post: visita in profondità il sottoalbero di T con radice in n Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Visite: Depth First Search DFS_aux (n, T) // Post: visita in profondità il sottoalbero di T con radice in n cominciando dalla radice visita n if not Leaf (n, T) then m Child (n, T) DFS_aux (m, T) while HasSibling (m, T) do m Sibling(m, T) Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Il tipo BinTree typedef struct tnode { T info; // etichetta struct tnode *left, *right; // puntatori ai figli sinistro e destro } tNode; typedef struct bintreeframe { int card; // numero dei nodi dell’albero tNode* root; // radice dell’albero } BinTreeFrame typedef BinTreeFrame* BinTree; Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Costruttori tNode* NewtNode (T etc, tNode* l, tNode* r) { tNode* n = new tNode; n->info = etc; n->left = l; n->right = r; return n; } BinTree NewBinTree (void) { BinTree bt = new BinTreeFrame; bt->card = 0; bt->root = NULL; return bt; Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Un esempio: la funzione Altezza int Altezza (tNode* n) // Pre: n != NULL // Post: ritorna l’altezza dell’albero con radice in n { return Altezza_aux(n); } int Altezza_aux (tNode*) // Post: ritorna l’altezza di tNode se != NULL, 0 altr. { int hl = 0, hr = 0; if (n->left == NULL && n->right == NULL) return 0; if (n->left != NULL) hl = Altezza_aux (n->left); if (n->right != NULL) hr = Altezza_aux (n->right); if (hl > hr) return hl + 1; return hr + 1; } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Visite in profondità void preorder (tNode* n) { if (n != NULL) { visit(n); preorder(n->left); preorder(n->right); } void inorder (tNode* n) { { inorder(n->left); visit(n); inorder(n->right); Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
La lista dei vertici in preordine (1) Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
La lista dei vertici in preordine (2) La soluzione ovvia è O(n2): Node* Preorder_List (tNode* n) { if (n == NULL) return NULL; return NewNode(n->info, concat (Preorder_List(n->left), Preorder_List(n->right)); } La complessità quadratica deriva dall’uso di concat nel caso in cui l’albero sia degenere sinistro. Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
La lista dei vertici in preordine (3) Esiste una soluzione ottima O(n): Node* Preorder_List2 (tNode* n, Node* l) { if (n == NULL) return l; return NewNode(n->info, Preorder_List2(n->left, Preorder_List2(n->right,l)); } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6