320 likes | 477 Views
alberi. tipo astratto, implementazione, algoritmi. argomenti. tipo astratto albero definizione implementazione in Java algoritmi di visita alberi binari implementazione di alberi binari in Java. tipo di dato astratto albero.
E N D
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
tipo di dato astratto albero • insieme vuoto di nodi oppure costituito da una radice R e da 0 o più alberi (detti sottoalberi) • la radice di ogni sottoalbero è collegata a R da un arco (orientato) R es.: radice R con n sottoalberi T1 T2 Tn ASD - Alberi
terminologia • genitore, figlio, fratello • concetti intuitivi • nodo • foglia se ha zero figli • interno se ha almeno un figlio radice nodo interno foglia ASD - Alberi
terminologia/2 • livello di un nodo • lunghezza (n.ro nodi) percorso radice-nodo • ramo • percorso radice-foglia • altezza albero • lunghezza (n.ro nodi) ramo più lungo livello radice = 1 altezza = 3 ASD - Alberi
alberi? ASD - Alberi
esempi di alberi • alberi genealogici • gerarchie di ereditarietà • ad es., in Java • classificazioni di specie animali • organizzazione del territorio • continente, nazione, regione, provincia ecc • (alcuni) organigrammi • file system • domini Internet ASD - Alberi
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
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
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
rappresentazionedei nodi in Java • nodi class TreeNode { Object element; TreeNode firstChild; TreeNode nextSibling; TreeNode parent; } ASD - Alberi
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
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
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
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
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
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
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
2 1 7 1 4 6 2 3 5 1 3 6 3 5 7 4 6 7 2 4 5 visite in profondità preordine inordine postordine ASD - Alberi
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
1 2 3 4 5 6 7 visita in ampiezza BFS ASD - Alberi
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; } implementazione minima ASD - Alberi
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
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
alberi binari/visita inordine void treeInorder(BinaryNode v) { if(v == null) return; treeInorder(T.leftChild(v)); <visita v> treeInorder(T.rightChild(v)); } ASD - Alberi
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
alberi binari/visita in ampiezza void bfs(v) { queue.enqueue(v); 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
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
1 2 3 4 - 6 7 - uso di vettori • ogni nodo v è memorizzato in posizione p(v) • 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 p(v)=2p(u)+1 1 3 2 7 6 4 ASD - Alberi
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 "destra") ASD - Alberi
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
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