Salta al contenuto
Note per Studenti Alberi

Alberi

In questa pagina 6

Un albero è una collezione di nodi con struttura gerarchica padre-figlio, con i collegamenti strettamente necessari a tenerli connessi (una lista è il caso estremo). Applicazioni: dizionari e code con priorità (vedi HeapAlbero binario completo e sua altezza floor(log2 n); heap = albero completo con heap-order property; proprietà (radice minima, cammini non decrescenti); rappresentazione su array con level numbering; insert con up-heap bubbling, removeMin con down-heap bubbling, rimozione di una entry qualsiasi; invarianti e costi Theta(log n); esempio svolto.Heap →, Alberi binari di ricercaAlbero binario di ricerca come albero binario proprio con entry nei nodi interni e foglie vuote; inorder crescente; TreeSearch; get, put e remove (due casi, con predecessore inorder) in Theta(h); altezza fino a n-1; esempi di inserimenti; alberi aumentati con campi size e max e algoritmi di conteggio e interrogazione in O(h).Alberi binari di ricerca →), file system, albero della ricorsione (vedi Algoritmi ricorsiviAlgoritmi ricorsivi come induzione eseguita; albero della ricorsione e record di attivazione nello stack; esempi ReverseArray, LinearSum, Power in tempo logaritmico, Fibonacci ricorsivo (esponenziale) e con memoizzazione; analisi della complessità con l'albero della ricorsione e correttezza per induzione.Algoritmi ricorsivi →), alberi di decisione, codici di Huffman, alberi filogenetici.

Definizione

Un albero radicato TT è una collezione di nodi che, se non vuota, soddisfa:

  • esiste un nodo speciale rr, la radice;
  • ogni v≠rv \ne r ha un unico padre uu (vv è figlio di uu);
  • risalendo di padre in padre da ogni nodo si arriva a rr.

Definizione ricorsiva: T={r}∪T1∪⋯∪TkT = \{r\} \cup T_1 \cup \dots \cup T_k con k≥0k \ge 0, dove T1,…,TkT_1, \dots, T_k sono alberi non vuoti le cui radici sono figlie di rr.

Terminologia

Termine Significato
antenato di yy x=yx = y oppure xx antenato del padre di yy
discendente di yy xx tale che yy è antenato di xx
nodo interno nodo con almeno un figlio
nodo esterno o foglia nodo senza figli
sottoalbero TvT_v vv con tutti i suoi discendenti
albero ordinato per ogni nodo interno è fissato un ordine lineare tra i figli

Dato un albero ordinato, due nodi u,vu, v allo stesso livello: uu è a sinistra di vv se uu precede vv nella visita in preorder (vedi Visite di alberiVisite in preorder e postorder come schemi generali (template) da adattare; complessità Theta(n + somma dei costi di visita) perché la somma dei figli è n-1; esempi (indice di un libro, spazio occupato in un file system); profondità con il preorder, altezza con il postorder; antenato comune più basso.Visite di alberi →).

Profondità, livello, altezza

  • Profondità depth(v)\text{depth}(v) = numero di antenati di vv meno 1; ricorsivamente: depth(r)=0\text{depth}(r) = 0, altrimenti 1+depth(padre(v))1 + \text{depth}(\text{padre}(v)).
  • Livello ii = insieme dei nodi a profondità ii.
  • Altezza di un nodo: height(v)=0\text{height}(v) = 0 se vv è foglia, altrimenti 1+max⁡w figlio di vheight(w)1 + \max_{w \text{ figlio di } v} \text{height}(w). Altezza dell'albero: height(T)=height(r)\text{height}(T) = \text{height}(r).

Proposizione. Se TT non è vuoto, height(T)=max⁡{depth(v):v foglia}\text{height}(T) = \max\{\text{depth}(v) : v \text{ foglia}\}.

Dimostrazione (induzione sull'altezza). Se TT è la sola radice, l'altezza è 00 e l'unica foglia è rr, di profondità 00. Altrimenti T={r}∪T1∪⋯∪TkT = \{r\} \cup T_1 \cup \dots \cup T_k: ogni foglia di TT sta in un TiT_i e ha profondità in TT pari a 11 più la profondità in TiT_i. Per ipotesi induttiva la massima profondità delle foglie di TiT_i è height(Ti)\text{height}(T_i), quindi la massima profondità delle foglie di TT è 1+max⁡iheight(Ti)=height(r)1 + \max_i \text{height}(T_i) = \text{height}(r). □\square

Interfaccia e implementazione

Metodi tipici: root(), parent(v), children(v), isRoot(v), isInternal(v), isExternal(v), size(). L'implementazione a struttura collegata dà a ogni nodo un riferimento al padre e alla collezione dei figli; spazio Θ(n)\Theta(n) e children(v) in tempo proporzionale al numero di figli.

Algoritmi su profondità e altezza

Profondità (ricorsivo, risalendo):

Algoritmo depth(T, v)
Input: nodo v di T          Output: profondità di v
if T.isRoot(v) then return 0
else return 1 + depth(T, T.parent(v))

Costo Θ(depth(v)+1)\Theta(\text{depth}(v) + 1), al caso pessimo Θ(n)\Theta(n) (albero ridotto a un cammino). Versione iterativa: si sale con un ciclo contando i passi.

Altezza di un nodo (dal basso, usando le altezze dei figli):

Algoritmo height(T, v)
Input: nodo v di T          Output: altezza di v
h <- 0
foreach w in T.children(v) do h <- max(h, 1 + height(T, w))
return h

Costo: height\text{height} è chiamato una volta per nodo; la chiamata su uu costa Θ(1+cu)\Theta(1 + c_u) con cuc_u numero di figli. Poiché in un albero con nn nodi ∑ucu=n−1\sum_{u} c_u = n - 1 (ogni nodo non radice ha un solo padre), il totale è ∑u(1+cu)=2n−1∈Θ(n)\sum_u (1 + c_u) = 2n - 1 \in \Theta(n). È una visita in postorder (vedi Visite di alberiVisite in preorder e postorder come schemi generali (template) da adattare; complessità Theta(n + somma dei costi di visita) perché la somma dei figli è n-1; esempi (indice di un libro, spazio occupato in un file system); profondità con il preorder, altezza con il postorder; antenato comune più basso.Visite di alberi →).

Una strategia lenta (heightBad\text{heightBad}). Calcolare l'altezza come massima depth tra le foglie, invocando depth da ciascuna foglia, è corretto per la proposizione ma costa Ω(n2)\Omega(n^2). Istanza cattiva: un cammino di n/2n/2 nodi con n/2n/2 foglie attaccate al nodo più basso; ognuna delle n/2n/2 foglie ha profondità ≥n/2\ge n/2, e ogni chiamata a depth costa almeno questo: n2⋅n2=n24\frac n2 \cdot \frac n2 = \frac{n^2}{4} operazioni.

Errori comuni

  • Confondere profondità e altezza di un nodo: la prima si conta dalla radice in giù, la seconda dalla foglia più lontana in su. In una foglia l'altezza è 00, la profondità no.
  • Dire che l'altezza dell'albero è il numero di nodi o di livelli: è il numero di archi del cammino più lungo (un albero con la sola radice ha altezza 00).
  • Stimare height come Θ(n⋅figli)\Theta(n \cdot \text{figli}): il costo totale è Θ(n)\Theta(n) perché ∑cu=n−1\sum c_u = n-1.

Versione ripasso

  • Albero radicato: radice rr; ogni v≠rv \ne r ha un unico padre; da ogni nodo si risale a rr. Ricorsivo: T={r}∪T1∪⋯∪TkT = \{r\} \cup T_1 \cup \dots \cup T_k.
  • Termini: antenato (x=yx = y o antenato del padre), discendente, nodo interno (≥1\ge 1 figlio), foglia (nessun figlio), sottoalbero TvT_v, albero ordinato (figli ordinati).
  • depth(r)=0(r) = 0, depth(v)=1+depth(padre)\text{depth}(v) = 1 + \text{depth}(\text{padre}); livello ii = nodi a profondità ii; height(foglia) =0= 0, height(v)=1+max⁡w figlioheight(w)\text{height}(v) = 1 + \max_{w \text{ figlio}} \text{height}(w).
  • Proposizione: height(T)=max⁡{depth(v):v foglia}\text{height}(T) = \max\{\text{depth}(v) : v \text{ foglia}\}.
  • Algoritmi: depth ricorsivo Θ(depth+1)≤Θ(n)\Theta(\text{depth}+1) \le \Theta(n); height in postorder Θ(n)\Theta(n) perché ∑ucu=n−1\sum_u c_u = n-1 (costo ∑(1+cu)=2n−1\sum (1 + c_u) = 2n-1); heightBad (depth da ogni foglia) Ω(n2)\Omega(n^2): cammino di n/2n/2 nodi con n/2n/2 foglie in fondo.
  • Implementazione: struttura collegata (riferimento al padre e ai figli), spazio Θ(n)\Theta(n); metodi root, parent, children, isRoot, isInternal, isExternal, size.
  • Algoritmi: depth(T,v): radice →0\to 0, altrimenti 1+depth(parent)1 + \text{depth}(\text{parent}); height(T,v): h←0h \leftarrow 0, per ogni figlio ww: h←max⁡(h,1+height(w))h \leftarrow \max(h, 1 + \text{height}(w)).
  • Errori: profondità vs altezza; altezza = numero di archi (radice sola =0= 0); costo di height non Θ(n⋅figli)\Theta(n \cdot \text{figli}). Vedi Visite di alberiVisite in preorder e postorder come schemi generali (template) da adattare; complessità Theta(n + somma dei costi di visita) perché la somma dei figli è n-1; esempi (indice di un libro, spazio occupato in un file system); profondità con il preorder, altezza con il postorder; antenato comune più basso.Visite di alberi →.

Esercizi su questo argomento

Teoria collegata