lezione 9 min-heap binario Heap e Alberi posizionali generali

Documenti analoghi
Correzione prima esercitazione: metodo distinct

Problemi di ordinamento

Un heap binario è un albero binario con le seguenti caratteristiche:

Heap e Code di Priorità

Code a priorità Una coda a priorità è una struttura dati astratta che permette di rappresentare un insieme di elementi su cui è definita una

Esercitazione 3. Heapsort

Spesso sono definite anche le seguenti operazioni:

Informatica 3. Informatica 3. LEZIONE 17: Alberi generici. Lezione 17 - Modulo 1. Introduzione. ADT dell albero generico.

Alberi. Strutture dati: Alberi. Alberi: Alcuni concetti. Alberi: definizione ricorsiva. Alberi: Una prima realizzazione. Alberi: prima Realizzazione

Informatica 3. LEZIONE 17: Alberi generici. Modulo 1: Definizione e ADT Modulo 2: Implementazione Modulo 3: Alberi e classi di equivalenza

heap heap heap? max- e min-heap concetti ed applicazioni heap = catasta condizione di heap non è una struttura ordinata

Laboratorio di Programmazione II Corso di Laurea in Bioinformatica Dipartimento di Informatica - Università di Verona

ADT albero binario completo

Algoritmi e Strutture Dati & Laboratorio di Algoritmi e Programmazione

Strutture dati Alberi binari

Esercizi su programmazione ricorsiva 3

Dato un insieme S di n elementi totalmente ordinato, l'algoritmo di ordinamento detto HeapSort ha le seguenti caratteristiche:

PROGRAMMAZIONE II canale A-D luglio 2008 TRACCIA DI SOLUZIONE

d. Cancellazione del valore 5 e. Inserimento del valore 1

Esercizi parte 3. La classe ArrayBinTree dovra implementare, tra le altre, l operazione seguente: padre: dato un nodo, restituire l indice del padre.

Implementazione ADT: Alberi

Alberi binari e alberi binari di ricerca

Organigramma Gerarchia. (Tree) Nessuna persona può avere più di un superiore Ogni persona può essere superiore di altre

Il tipo astratto coda con priorità: specifiche sintattiche e semantiche. Realizzazioni.

Esercitazione 8. Corso di Tecniche di programmazione. Laurea in Ingegneria Informatica

Alberi binari e alberi binari di ricerca

Algoritmi e Strutture Dati

Alberi binari e alberi binari di ricerca

Laboratorio di Algoritmi e Strutture Dati. Code con Priorità

heap concetti ed applicazioni

Algoritmi e Strutture Dati Laboratorio 20/10/2008. Prof. Pier Luca Lanzi

Alberi binari di ricerca

Informatica 3. LEZIONE 16: Heap - Codifica di Huffmann. Modulo 1: Heap e code di priorità Modulo 2: Esempio applicativo: codifica di Huffmann

L albero e un tipo astratto di dati usato per rappresentare relazioni gerarchiche.

Università degli Studi di L Aquila Facoltà di Scienze M.F.N. Corso di Laurea in Informatica. Modulo di Laboratorio di Algoritmi e Strutture Dati

Algoritmi e Strutture Dati

Alberi Binario in Java

Algoritmi e Strutture di Dati

In questa lezione. Code di priorità. [CLRS01] cap. 6 da pag. 114 a pag Prof. E. Fachini - Intr. Alg. lunedì 17 settembre 2012

Alberi. Albero binario. Un albero binario è un albero (ordinato) in cui ciascun nodo può avere al massimo due figli (figlio destro e figlio sinistro)

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati

Heap, heapsort e code a priorità. Paolo Camurati Dip. Automatica e Informatica Politecnico di Torino

Tipi di dato e Strutture dati elementari

Esercitazione 6. Alberi binari di ricerca

lezione 5 Tipo di dato Lista Liste

Heap e code di priorità

Alberi. Definizioni principali

ALBERI : introduzione SOMMARIO ALBERI ALBERI. ALBERI: introduzione ALBERI BINARI: introduzione VISITE RICORSIVE DI ALBERI

Algoritmi e Strutture di Dati

Informatica 3. Informatica 3. LEZIONE 14: Alberi binari: introduzione. Lezione 14 - Modulo 1. Definizioni. Introduzione. Definizioni e proprietà

Alberi. In informatica, un albero è un modello astratto di una struttura dati gerarchica

Alberi ed Alberi Binari

ADT Dizionario. Ordered search table. Supponiamo che sia definita una relazione d'ordine totale sulle chiavi del dizionario D:

Alberi Binari Alberi Binari

Struttura dati Dizionario

argomenti alberi terminologia tipo di dato astratto albero tipo astratto, implementazione, algoritmi es.: radice R con n sottoalberi radice

alberi tipo astratto, implementazione, algoritmi

Code con priorità. Moreno Marzolla Dip. di Scienze dell'informazione Università di Bologna.

Albero in cui ogni nodo ha al più due figli. I figli di un nodo costituiscono una coppia ordinata

Per semplicità eliminiamo le ripetizioni nell'albero.

Prova di Algoritmi e s.d. (1o anno) 17 Settembre TESTO e RISPOSTE

ALGORITMI E STRUTTURE DATI

Lezione 12 Tabelle Hash

Espressioni aritmetiche

Programmazione in Java Parte II

ADT Coda con priorità

Algoritmi e strutture dati 16 Dicembre 2004 Canali A L e M Z Cognome Nome Matricola

Laboratorio di Algoritmi e Strutture Dati. Aniello Murano. people.na.infn.it/~murano/ Murano Aniello - Lab. di ASD Terza Lezione

Algoritmi e Strutture Dati

Gli heap. Sommario. Algoritmi e Programmazione Avanzata. Fulvio CORNO - Matteo SONZA REORDA Dip. Automatica e Informatica Politecnico di Torino

Alberi binari di ricerca

In questa lezione Strutture dati elementari: Pila Coda Loro uso nella costruzione di algoritmi.

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

Esercizio. Strutture Dati

GLI ALBERI BINARI DI RICERCA. Cosimo Laneve

Esercizio 1 (6 punti)

Alberi. CORDA Informatica. A. Ferrari. Testi da. Marco Bernardo Edoardo Bontà. Dispense del Corso di. Algoritmi e Strutture Dati

STRUTTURE DATI: OLTRE GLI ARRAY LISTE

In questa lezione. Heap binario heapsort. [CLRS10] cap. 6, par Prof. E. Fachini - Intr. Alg.

Alberi e alberi binari I Un albero è un caso particolare di grafo

Algoritmi e Strutture Dati & Laboratorio di Algoritmi e Programmazione

Il TDA BinaryTree. Albero Binario. Albero sintattico. Applicazioni. Albero delle decisioni binario. Albero binario di ricerca

Alberi Binari di Ricerca

Alberi e alberi binari I Un albero è un caso particolare di grafo

Alberi binari (radicati e ordinati) della radice Il padre del nodo 5 e del nodo 3

Albero binario. Alberi binari (introduzione) Terminologia. Alberi di ricerca binaria (BST)

QuickSort Università degli Studi di Milano

Liste concatenate. Collezione ordinata di nodi. Carlo Paolo Simona. Anna. ciascun nodo contiene due riferimenti:

Esempi. Albero di interi. Struttura che non è un albero!

Algoritmi e Strutture di Dati

Transcript:

lezione 9 Heap e Alberi posizionali generali min-heap binario Un min-heap è un albero binario quasi completo in cui ogni nodo i diverso dalla radice soddisfa la seguente proprietà: il valore memorizzato in parent(i) è minore o uguale quello memorizzato nel nodo i Equivalentemente, si può dire che: la radice ha valore minimo il valore dei nodi cresce muovendo dalla radice verso le foglie lungo tutti i cammini 10 Un max-heap può essere definito analogamente.

min-heap: inserimento Per mantenere l!albero quasi completo si inserisce un nuovo elemento come foglia posta a destra dell!ultima foglia, cioè l!albero viene completato per livelli. La nuova foglia viene poi sistemata nella posizione corretta del cammino che porta dalla sua posizione alla root. 10 25 min-heap: rimozione minimo L estrazione del minimo consiste nella rimozione della radice dello heap. Come si realizza questa operazione? - eliminando l!ultima foglia inserita e salvandone chiave e valore in radice - ripristinando la proprietà di essere min-heap (usando la procedura heapify) 25

Heap binari con array Lo heap binario si rappresenta in modo efficiente usando un array che, letto da sinistra a destra, rappresenta la visita in ampiezza dell!albero. Ogni nuovo elemento si inserisce dopo l!ultima foglia più a destra (cioè nella prima posizione libera dell!array) e quindi l!albero viene riempito per livelli. Il fatto che lo heap sia un albero quasi completo permette di stabilire delle relazioni tra i figli e il padre di ogni nodo e l!indice in cui compare nell!array. Precisamente, supponendo che gli indici dell!array partano da 1 si ha: - parent(i) = i/2 - left(i) = 2i - right(i) = 2i+1 La complessità delle operazioni di inserimento e rimozione è O(lg n) dove n è il numero di elementi dello heap. Tipo di dato Coda a Priorità Il tipo di dato coda a priorità permette di gestire collezioni di elementi a cui sono associate chiavi prese da un dominio totalmente ordinato. I dati ammessi sono quindi un insieme di coppie (elem, key), dove la chiave key esprime la priorità associata all!elemento elem nella coda. Si tratta cioè di una coda in cui la disciplina FIFO viene modificata dalla priorità associata a ciascun elemento: nelle code a max-priorità, maggiore è la priorità e più velocemente l!elemento uscirà dalla coda; nelle code a min-priorità, minore è la priorità e più velocemente l!elemento uscirà dalla coda.

Tipo di dato Coda a Priorità Le operazioni definite per una coda a max-priorità sono: insert(q, elem,p): inserimento di elem con priorità p extract-max(q): elimina e restituisce l elemento di priorità massima maximum(q): ritorna l elemento con priorità massima increase-key(q,x,k): aumenta il valore della chiave dell elemento x al nuovo valore di k, che si suppone sia almeno pari al valore corrente della chiave associata ad x Le operazioni definite per una coda a min-priorità sono analoghe. Realizzazione di code a priorità Le code priorità possono essere realizzate in vari modi (ad esempio: con array, liste concatenate, alberi). In particolare, esse possono essere realizzate in modo efficiente con heap binari. Se una coda a max-priorità viene realizzata con un max-heap binario, la complessità delle operazioni definite è: - inserimento! O(lg n) - estrazione del massimo! O(lg n) - interrogazione del massimo! O(1) - incremento chiave di un elemento! O(lg n) dove n è il numero di elementi in coda 25

Heap ternari Gli heap ternari sono una generalizzazione degli heap binari in cui gli alberi non sono più binari ma ternari (cioè sono alberi in cui un nodo può avere tre figli). La definizione di un max-heap ternario è la seguente: Un max-heap ternario è un albero ternario quasi completo in cui ogni nodo i diverso dalla radice soddisfa la seguente proprietà: il valore memorizzato in parent(i) è maggiore o uguale quello memorizzato nel nodo i Un min-heap ternario è definito in modo analogo. 25 min-heap ternario: esempio 5 10 8 20 11 16 30 9 25 40 Le operazioni di inserimento e rimozione del minimo vengono realizzate in modo analogo al min-heap binario. 25

Heap ternari con array Anche uno heap ternario si rappresenta in modo effiiente con un array. Cosa cambia rispetto allo heap binario? quasi nulla! Anche in questo caso l!array, letto da sinistra a destra,, rappresenta la visita in ampiezza dell!albero. Ogni nuovo elemento si inserisce dopo l!ultima foglia più a destra (cioè nella prima posizione libera dell!array) e quindi l!albero viene riempito per livelli. Heap ternari con array Anche nel caso ternario, il fatto che lo heap sia un albero quasi completo permette di stabilire delle relazioni tra i figli e il padre di ogni nodo e l!indice in cui compare nell!array. Precisamente, supponendo che gli indici dell!array partano da 1 si ha: - parent(i) = i/3 - first(i) = 3i - 1 - second(i) = 3i - third(i) = 3i + 1 La complessità delle operazioni di inserimento e rimozione è O(lg 3 n) dove n è il numero di elementi dello heap.

Code a priorità con heap ternari Abbiamo visto che le code a priorità vengono realizzate in modo efficiente con gli heap binari. Cosa cambia con gli heap ternari? Se la coda viene realizzata con un max-heap ternario, la complessità delle operazioni definite è: - inserimento! O(lg 3 n) - estrazione del massimo! O(lg 3 n) - interrogazione del massimo! O(1) - incremento chiave di un elemento! O(lg 3 n) dove n è il numero di elementi in coda 25 Heap k-ari Le definizioni che abbiamo visto per gli heap si possono generalizzare al caso di alberi k-ari. Un albero è k-ario se tutti i suoi nodi hanno al più k figli. Un albero k-ario è completo se tutti i suoi nodi interni hanno esattamente k figli e tutte le foglie si trovano allo stesso livello. Quindi: Un min-heap k-ario è un albero k-ario quasi completo in cui ogni nodo i diverso dalla radice soddisfa la seguente proprietà: il valore memorizzato in parent(i) è minore o uguale quello memorizzato nel nodo i Si possono analogamente estendere - la rappresentazione degli heap k-ari con array e - la realizzazione di code a priorità 25 con heap k-ari

Alberi posizionali generali Definizione ricorsiva: Un albero posizionale T è un insieme di nodi tale che: - o è vuoto - oppure contiene un nodo radice x, e un insieme di alberi posizionali T1, T2,,Tn detti primo, secondo, n-esimo sottoalbero di T e tali che, per ogni i: - Ti è figlio di x - se Ti non è vuoto allora anche T1, Ti-1 non sono vuoti. Analogamente agli alberi binari, sono definiti anche per gli alberi generali degli algoritmi di visita in ampiezza e profondità (già presentati dalla prof. Bossi). Alberi: rappresentazione figliofratello Usiamo una struttura collegata per rappresentare un albero generale. Allora un albero generale T è individuato dalla sua radice e ciascun nodo dell!albero contiene le seguenti informazioni: - il dato memorizzato nel nodo (key) - il riferimento al primo figlio (child) - il riferimento al fratello successivo (sibling) - il riferimento al padre (parent) opzionale NOTA: -le foglie non hanno figli -la radice non ha fratelli

Esempio d Alberi: assunzioni per l!implementazione Operazioni di spostamento: utilizziamo un cursore per spostarci all!interno dell!albero - reset: riporta il cursore sulla radice - movedown(i) si sposta sull!i-esimo figlio, se possibile - moveup si sposta sul padre, se possibile Inserimento: - il nuovo nodo viene inserito come figlio del nodo corrente aggiungendolo come fratello dell!ultimo figlio (sempre possibile!) Cancellazione: - il nodo corrente viene cancellato solo se è una foglia - dopo la cancellazione il nodo corrente diventa il padre del nodo cancellato (se esiste)

Struttura del package Trees Il package comprende i seguenti file: - Tree.java: interfaccia per gli alberi generali - TreeNode.java: classe che permette di memorizzare un nodo - GenTree.java: classe che realizza le operazioni definite nell!interfaccia Tree.java classe TreeNode package Trees; class TreeNode { Object key; TreeNode parent; TreeNode child; TreeNode sibling; // valore associato al nodo // padre del nodo // primo figlio del nodo // fratello destro del nodo // post: ritorna un albero di un solo nodo, con valore value e // sottoalberi vuoti TreeNode(Object ob) { key = ob; parent = child = sibling = null; // post: ritorna un albero contenente value e i sottoalberi // specificati TreeNode(Object ob, TreeNode parent, child, sibling) { key = ob; this.parent = parent; this.child = child; this.sibling = sibling;

Interfaccia Tree package Trees; public interface Tree { // post: ritorna il numero di elementi dell'albero public int size(); // post: ritorna true sse l'albero e' vuoto public boolean isempty(); // post: svuota l'albero public void clear(); // pre: ob non nullo // post: se l'albero e' vuoto, inserisce ob come root. // Altrimenti inserisce ob come figlio del nodo corrente. // Ritorna true. public boolean insert(object ob); // pre: albero non vuoto // post: se l'elemento corrente e' una foglia, la rimuove e ne ritorna // il valore; il nuovo elemento corrente e' il padre del nodo // rimosso (se esiste). // Altrimenti ritorna null public Object remove (); Interfaccia Tree // pre: albero non vuoto! // post: ritorna il valore del nodo puntato da cursor public Object getvalue(); // pre: albero non vuoto e ob diverso da null // post: imposta il valore del nodo puntato da cursor public void setvalue(object ob); // post: cursor si sposta sulla radice public void reset(); // post: se possibile cursor si sposta sul figlio in posizione // childindex e ritorna true; altrimenti rimane dov'e' e // ritorna false public boolean movedown (int childindex); // post: se possibile sposta cursor sul nodo padre e ritorna true; // altrimenti ritorna false; public boolean moveup (); // post: ritorna una stringa che rappresenta l'albero, secondo la // visita in profondita public String preordervisit();

classe GenTree (1) package Trees; public class GenTree { private TreeNode root; private int count; private TreeNode cursor; // radice dell'albero // numero di nodi dell'albero // riferimento al nodo corrente // post: costruisce un albero vuoto public GenTree() { clear(); // post: svuota l'albero public void clear() { root = cursor = null; count = 0; // post: ritorna il numero di nodi dell'albero public int size() { return count; // post: ritorna true se l'albero e' vuoto; false altrimenti public boolean isempty() { return count == 0; // pre: albero non vuoto! // post: ritorna il valore del nodo puntato da cursor public Object getvalue() { return cursor.key; // pre: albero non vuoto e ob diverso da null // post: imposta il valore del nodo puntato da cursor public void setvalue(object ob) { cursor.key = ob; classe GenTree (2) // pre: ob non nullo // post: l'oggetto e' inserito come figlio del nodo corrente, // o come radice se l'albero e' vuoto. Ritorna true. public boolean insert (Object ob) { if (isempty()) cursor = root = new TreeNode(ob); else { if (cursor.child == null) cursor.child = new TreeNode(ob, cursor, null,null); else { TreeNode index = cursor.child; while (index.sibling!= null) index = index.sibling; index.sibling = new TreeNode(ob,cursor, null,null); count++; return true;

classe GenTree (3) // pre: albero non vuoto // post: se cursor e' una foglia, la rimuove e ne ritorna il valore; // cursor viene assegnato al padre del nodo rimosso (se esiste) // Altrimenti ritorna null public Object remove () { if (cursor.child!= null) return null; Object temp = cursor.key; if (cursor == root) cursor = root = null; else { if (cursor.parent.child == cursor) // cursor e' il primo figlio cursor.parent.child = cursor.sibling; else { TreeNode index = cursor.parent.child; while (index.sibling!= cursor) index = index.sibling; index.sibling = cursor.sibling; cursor = cursor.parent; count --; return temp; classe GenTree (4) // post: cursor si sposta sulla radice public void reset() { cursor = root; // post: se possibile cursor si sposta sul figlio in posizione childindex // e ritorna true; altrimenti rimane dov'e' e ritorna false public boolean movedown (int childindex) { if (isempty() cursor.child == null childindex < 1) return false; TreeNode index = cursor.child; int i; for (i = 1; i<childindex && index.sibling!= null; i++) index = index.sibling; if (i == childindex) { cursor = index; return true; else return false;

classe GenTree (5) // post: se possibile sposta cursor sul nodo padre e ritorna true; // altrimenti ritorna false; public boolean moveup () { if (isempty() cursor.parent == null) return false; else { cursor=cursor.parent; return true; // post: ritorna una stringa che rappresenta l'albero public String DFvisit() { StringBuffer sb = new StringBuffer(); sb.append("tree: <"); if (root!= null) DFformat(root,sb); sb.append(">"); return sb.tostring(); classe GenTree (6) // pre: n diverso da null // post: appende a sb una stringa che rappresenta il sottoalbero con // radice n private void DFformat(TreeNode n, StringBuffer sb) { sb.append(" " + n.key.tostring() + " "); if (n.child!= null) { sb.append("<"); DFformat(n.child,sb); sb.append("> "); if (n.sibling!= null) DFformat(n.sibling,sb);