alberi
tipo astratto, implementazione,
algoritmi
argomenti

tipo astratto albero




definizione
implementazione in Java
algoritmi di visita
alberi binari

implementazione di alberi binari in Java
ASD - Alberi
2
tipo di dato astratto albero


insieme vuoto di nodi oppure costituito da
una radice R e da 0 o più alberi (sottoalberi)
la radice di ogni sottoalbero è collegata a R
da un arco
R
es.: radice R con n
sottoalberi
T1
ASD - Alberi
T2
Tn
3
terminologia

genitore, figlio, fratello


radice
concetti intuitivi
nodo interno
nodo


foglia se ha zero figli
interno se ha almeno un
figlio
ASD - Alberi
foglia
4
terminologia/2

livello di un nodo


lunghezza (n.ro nodi)
percorso radice-nodo
ramo


livello radice = 1
percorso radice-foglia
altezza albero

altezza = 3
lunghezza (n.ro nodi)
ramo più lungo
ASD - Alberi
5
alberi?
ASD - Alberi
6
esempi di alberi


alberi genealogici
gerarchie di ereditarietà



classificazioni di specie animali
organizzazione del territorio




ad es., in Java
continente, nazione, regione, provincia ecc
(alcuni) organigrammi
file system
domini Internet
ASD - Alberi
7
rappresentazione di alberi con
liste collegate
livello di C = 3
R
B
A
Primo figlio
di R
C
Fratello di A
Elemento
Riferimento al prossimo fratello
Riferimento al primo figlio
ASD - Alberi
8
operazioni sugli alberi

operazioni più importanti






element(v): restituisce l’elemento
memorizzato nel nodo v
root(): restituisce la radice dell’albero
parent(v): restituisce il genitore del nodo v
children(v): restituisce i figli di v
isLeaf(v): restituisce true se v è una foglia
isRoot(v): restituisce true se v è la radice
ASD - Alberi
9
operazioni sugli alberi

Altre operazioni





livello di un nodo
altezza dell’albero
# nodi
# foglie
arità


max # di figli di un nodo dell’albero
isEmpty

true se l’albero ha zero nodi
ASD - Alberi
10
rappresentazione
dei nodi in Java

nodi
class TreeNode {
Object element;
TreeNode firstChild;
TreeNode nextSibling;
TreeNode parent;
}
ASD - Alberi
11
tipo astratto albero in Java
public interface Tree {
Object element(TreeNode v);
TreeNode root();
TreeNode parent(TreeNode v);
ListIterator children(TreeNode v);
boolean isLeaf(TreeNode v);
boolean isRoot(TreeNode v);
}
ASD - Alberi
12
algoritmi su alberi

livello di un nodo
public int level(TreeNode v) {
if(this.isRoot(v))
return 1;
else
return 1 + level(this.parent(v));
}

costo proporzionale all’altezza: O(n )
ASD - Alberi
13
algoritmi su alberi/2


altezza di un
(sotto)albero
costo
proporzionale al
numero di nodi:
(n )
viene esaminato
ogni nodo
 ciascun nodo
viene esaminato
una sola volta

Algorithm height(v) {
if(v == null) return 0;
if(isLeaf(v)) return 1;
w = v.firstChild;
hmax = height(w);
while(w.nextSibling != null) {
w = w.nextSibling;
h = height(w);
if(h > hmax) hmax = h;
}
return 1 + hmax;
}
ASD - Alberi
14
algoritmi su alberi/3

visita (o attraversamento) di un albero

in profondità (depth-first search, a
scandaglio): DFS



vengono visitati i rami, uno dopo l’altro
tre varianti
in ampiezza (breadth-first search, a
ventaglio): BFS

a livelli, partendo dalla radice
ASD - Alberi
15
visite in profondità/preordine

in preordine (preorder, o ordine anticipato)

dato un nodo v
visita v
 visita i sotto-alberi aventi come radice i figli di v, da
sinistra verso destra
void treePreorder(root) {
if(root == null) return;
<visita root>
r = root.firstChild
while (r != null) {
treePreorder(r);
r = r.nextSibling;
}
ASD - Alberi
}

16
visite in profondità/inordine

in ordine simmetrico (inorder)

dato un nodo v con k sotto-alberi



visita il primo sotto-albero (radice v.firstChild)
visita v
visita gli altri k-1 sotto-alberi
void treeInorder(root) {
if(root == null) return;
r = root.firstChild;
treeInorder(r);
<visita root>
r = r.nextSibling;
while (r != null) {
treeInorder(r);
r = r.nextSibling;
}
}
ASD - Alberi
17
visite in profondità/postordine

in postordine (postorder, o ordine posticipato)

dato un nodo v
visita i sotto-alberi aventi come radice i figli di v, da
sinistra verso destra
 visita v
void treePostorder(root) {
if(root == null) return;
r = root.firstChild
while (r != null) {
treePostorder(r);
r = r.nextSibling;
}
<visita root>
ASD - Alberi
}

18
visite in profondità
2
1
2
3
4
1
5
6
preordine
7
7
4
3
1
6
5
inordine
ASD - Alberi
7
3
2
6
4
5
postordine
19
visita in ampiezza

breadth-first search (BFS), usa una coda

dato un nodo v
void bfs(v) {
if(v == null) return;
queue.enqueue(v);
while (!queue.isEmpty()) {
v = queue.dequeue();
v.visit();
w = v.firstChild;
while(w != null) {
queue.enqueue(w);
w = w.nextSibling;
}
}
ASD - Alberi
20
visita in ampiezza
1
2
3
4
5
6
7
BFS
ASD - Alberi
21
alberi binari


un albero si dice binario se ogni nodo può
avere al più 2 figli
la rappresentazione si semplifica
public class BinaryNode {
protected Object element;
protected BinaryNode leftChild;
protected BinaryNode rightChild;
}
ASD - Alberi
22
ADT albero binario in Java
public interface BinaryTree {
Object element(BinaryNode v);
BinaryNode root();
BinaryNode parent(BinaryNode v);
BinaryNode leftChild(BinaryNode v);
BinaryNode rightChild(BinaryNode v);
boolean isLeaf(BinaryNode v);
boolean isRoot(BinaryNode v);
}
ASD - Alberi
23
alberi binari/visita in preordine
void treePreorder(BinaryNode v) {
if(v == null) return;
<visita v>
treePreorder(T.leftChild(v));
treePreorder(T.rightChild(v));
}
ASD - Alberi
24
alberi binari/visita inordine
void treeInorder(BinaryNode v) {
if(v == null) return;
treeInorder(T.leftChild(v));
<visita v>
treeInorder(T.rightChild(v));
}
ASD - Alberi
25
alberi binari/visita in postordine
void treePostorder(BinaryNode v)
{
if(v == null) return;
treePostorder(T.leftChild(v));
treePostorder(T.rightChild(v));
<visita v>
}
ASD - Alberi
26
alberi binari/visita in ampiezza
void bfs(v) {
queue.enqueue(p);
while (!queue.isEmpty()) {
p = (BSTNode) queue.dequeue();
p.visit();
if (p.leftChild != null)
queue.enqueue(p.leftChild);
if (p.rightChild != null)
queue.enqueue(p.rightChild);
}
}
ASD - Alberi
27
strutture dati per alberi binari



vettori
rappresentazioni collegate
esercizi:


implementare l’interfaccia BinaryTree
usando una rappresentazione collegata
scrivere un programma che legga gli
elementi (stringhe) di un albero binario e li
stampi effettuando una visita in preordine
ASD - Alberi
28
uso di vettori

ogni nodo v è memorizzato in posizione p(v)



2
4
se v è la radice allora p(v)=1 (indice 0 in Java, C,
C++)
se v è il figlio sinistro di u allora p(v)=2p(u)
se v è il figlio destro di u allora
1
p(v)=2p(u)+1
2
1
3
4
3
6
7
6
7
ASD - Alberi
29
uso di vettori/2

implementazione statica: è necessaria
una stima del numero massimo di nodi
dell’albero


può portare a spreco di risorse
nel caso peggiore, un albero con n nodi
richiede un vettore con 2n-1 elementi (se
l’albero degenera in una catena)
ASD - Alberi
30
uso di vettori/3

in Java: si possono usare le classi Vector
(sincronizzata) o ArrayList (non sincronizzata)

Vector e ArrayList gestiscono anche il
ridimensionamento quando il numero di elementi
cresce oltre la capacità corrente


ciò porta a ritardi (per gestire l’allocazione di nuova
memoria)
esercizio: scrivere una classe che implementi
l’interfaccia BinaryTree usando ArrayList o
Vector
ASD - Alberi
31
rappresentazione collegata
public class LinkedBinaryTree implements BinaryTree {
private BinaryNode root; /* Rif. alla radice*/
private int size;
public LinkedBinaryTree() {
root = new BinaryTreeNode(null, null, null);
size = 0;
}
/* Altri metodi */
} /* Fine della classe */
ASD - Alberi
32