Alberi binari Corso di Informatica 2 a a
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 Colonnello 1 Maggiore 1, 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 1. Tipi di dato e strutture dati 1. Specifica e realizzazione 2. Rappresentazione in memoria 2. Liste 1. L’ADT delle liste 2. Realizzazione con vettori 3. Realizzazione con puntatori 3. Pile e code 1. 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, T 1, …, Tk sono alberi, v un vertice, allora {v, T 1, …, Tk } è un albero Un insieme di alberi è una foresta. albero foresta grafo ciclico Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Struttura induttiva degli alberi nodo 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: 1. la radice ha solo archi in uscita (albero sorgente) 2. 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 sorgente pozzo Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Parentele a è padre di b e c a b è figlio di a c b d è fratello di e d e f f è un discendente di a; a è un avo di f Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
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 Livello 0 Livello 1 Livello 2 Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Alberi ordinati Un albero è ordinato quando lo sono (linearmente) i suoi livelli a b d a c c = Come alberi ordinati siamo diversi 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 b c d Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Una specifica Sintassi • Tipi: Tree, Node • Operatori: New. Tree: void Tree Is. Empty. Tree: Tree boolean Ins. As. Root: Node, 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 Has. Sibling: Node, Tree Boolean Sibling: Node, Tree Node Ins. Tree: Node, Tree, Tree Del. Tree: Node, Tree Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Semantica degli operatori Con qualcosa si deve pur cominciare r Ins. As. Root(r, ) A cosa servono queste banalità? Ins. As. Root(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 r r a c b b d T Del. Tree(a, T ) Del. Tree(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 r a c b d r z T x a v c U d z x Ins. Tree(n, m, T, U ) = T b v Ins. Tree(c, a, T, U ) Pre: m, n sono nodi di T, U Post: T risulta da T inserendo U come figlio di m e 1. fratello successivo di n se n m 2. primo figlio di m se n = m Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Semantica degli operatori r a c b d r z x a v c z T U x b d v Ins. Tree(a, a, T, U ) Ins. Tree(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 1. fratello successivo di n se n m 2. primo figlio di m se n = m Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Semantica degli operatori Semantica New. Tree () = (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 , Has. Sibling (n, T) = true Post: m è il fratello successivo di n Is. Empty. Tree(T) = true se T = , false altr. Leaf(n, T) = b Pre: n T , b = true sse n è una foglia Has. Sibling(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 a c b d etichetta del nodo f e a b c d e f 0 1 1 2 2 3 1 2 3 4 5 6 Efficiente per rappresentare alberi pozzo di cardinalità (numero dei nodi) fissata indice del padre indice del nodo 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: a) b) BT(A) (albero vuoto) a A, l BT(A), r BT(A) Cons. Tree(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 T info left right r r a c a b b d T c d Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Codifica binaria di alberi k-ari a a b e c f b d g c e d 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 parent a info child sibling b c d e f g a b e c f d g Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
La cardinalità di un albero binario B Left(B) = l a Right(B) = r l r 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 Altezza (B) // Pre: B // Post: ritorna l’altezza di B return Altezza_aux (B) Si usa una funzione ausiliaria perché il caso di base B = è essenziale alla ricorsione 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 Conta. Foglie (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 T 1, …, 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 Conta. Foglie (T) // Post: ritorna il numero delle foglie di T if Is. Empty. Tree(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 Se m aveva un fratello, allora l’attuale valore di m è un nodo di T m Child(n, T) foglie Cf_aux (m, T) while Has. Sibling (m, T) do m Sibling (m, T) foglie + Cf_aux (m, T) return foglie 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 T 1, …, 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 Is. Emty. Tree(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 Has. Sibling (m, T) do m Sibling(m, T) DFS_aux (m, T) Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Il tipo Bin. Tree typedef struct tnode { T info; // etichetta struct tnode *left, *right; // puntatori ai figli sinistro e destro } t. Node; typedef struct bintreeframe { int card; // numero dei nodi dell’albero t. Node* root; // radice dell’albero } Bin. Tree. Frame typedef Bin. Tree. Frame* Bin. Tree; Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
Costruttori t. Node* Newt. Node (T etc, t. Node* l, t. Node* r) { t. Node* n = new t. Node; n->info = etc; n->left = l; n->right = r; return n; } Bin. Tree New. Bin. Tree (void) { Bin. Tree bt = new Bin. Tree. Frame; 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 (t. Node* n) // Pre: n != NULL // Post: ritorna l’altezza dell’albero con radice in n { return Altezza_aux(n); } int Altezza_aux (t. Node*) // Post: ritorna l’altezza di t. Node 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 (t. Node* n) { if (n != NULL) { visit(n); preorder(n->left); preorder(n->right); } } void inorder (t. Node* n) { if (n != NULL) { 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) a l r r Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
La lista dei vertici in preordine (2) La soluzione ovvia è O(n 2): Node* Preorder_List (t. Node* n) { if (n == NULL) return NULL; return New. Node(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_List 2 (t. Node* n, Node* l) { if (n == NULL) return l; return New. Node(n->info, Preorder_List 2(n->left, Preorder_List 2(n->right, l)); } Ugo de'Liguoro - Informatica 2 a. a. 03/04 Lez. 6
- Slides: 41