410 likes | 665 Views
Alberi binari. Corso di Informatica 2 a.a. 2003/04 Lezione 6. Cosa sono gli alberi?. Strutture gerarchiche di ogni tipo. Generale. Colonnello 1. Colonnello k. Maggiore 1,1. Maggiore 1,m. Maggiore k,1. Maggiore k,n. Capitano. Strutture gerarchiche di ogni tipo. Strutture dati
E N D
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 Colonnellok Maggiore1,1 Maggiore1,m 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 albero albero nodo 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 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 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
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 0 Livello 1 Livello 2 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 a b c d = Un albero è ordinato quando lo sono (linearmente) i suoi livelli Come alberi ordinati siamo diversi a 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 a b c d 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: 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 r r a b b c d DelTree(a, T ) 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 r r z z a b a b x x v v d c d c T U InsTree(c, a, T, 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 r r z z a b a b x x v v c d c d T U InsTree(a, a, T, 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 Semantica 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 etichetta del nodo a b c d e f indice del padre 0 1 1 2 2 3 1 2 3 4 5 6 indice del nodo a Efficiente per rappresentare alberi pozzo di cardinalità (numero dei nodi) fissata c b f d e 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 sottoalberosinistro e destro a l r Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Alberi binari realizzati con puntatori r T a info b a r b c d left right c d T Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
Codifica binaria di alberi k-ari a a d b c b g c e f 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 d b c child sibling g e f e d c g a f b Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 6
La cardinalità di un albero binario B a l r 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 returnAltezza_aux (B) Altezza_aux (B) // Post: ritorna l’altezza di B, 0 se B = ifB = 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 due casi di base else siano T1, …, Tk i sottoalberi con radici nei nodi figli di della radice di T return ContaFoglie (T) // Post: ritorna il numero delle foglie di T ifT = then return 0 else ifT ha un solo nodothen return 1 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: nT // 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) returnfoglie 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à ifT then visita Root(T) siano T1, …, Tk i sottoalberi con radici nei nodi figli di della radice di T fori 1 tokdo 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) DFS_aux (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 intAltezza (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à voidpreorder (tNode* n) { if (n != NULL) { visit(n); preorder(n->left); preorder(n->right); } } voidinorder (tNode* 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 a l r 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 ottimaO(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