Heap e code di priorità



Похожие документы
Algoritmi e Strutture Dati

Alberi binari e alberi binari di ricerca

ADT Coda con priorità

Heap Ordinamento e code di priorità. Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 9

Problemi di ordinamento

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

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

Alberi ed Alberi Binari

In questa lezione. Heapsort. ordinamento con complessità, nel caso peggiore, O(nlogn) [CLRS01] cap. 6 da pag. 106 a pag. 114

Alberi binari di ricerca

Laboratorio di Algoritmi e Strutture Dati. Code con Priorità

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

Esercitazione 6. Alberi binari di ricerca

Algoritmi (9 CFU) (A.A ) Heap e Algoritmo HeapSort. Prof. V. Cutello Algoritmi 1

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

Algoritmi di ordinamento: Array e ricorsione

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati. HeapSort

Esercitazione 3. Heapsort

In questa lezione Alberi binari di ricerca: la cancellazione

Alberi binari di ricerca

Alberi Binari di Ricerca

Esercizi su alberi binari

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

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

Alberi Binari di Ricerca

Algoritmi e Strutture Dati

Esercizio 1. E vero che in un AVL il minimo si trova in una foglia o nel penultimo livello? FB = -1. livello 0 FB = -1. livello 1 FB = -1.

Array e Oggetti. Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 1. Dispensa 12. A. Miola Dicembre 2006

Problem Set 2 docente: Luciano Gualà

Dati e Algoritmi I (Pietracaprina) Esercizi su Priority Queue e Heap

Транскрипт:

Heap e code di priorità Violetta Lonati Università degli studi di Milano Dipartimento di Scienze dell Informazione Laboratorio di algoritmi e strutture dati Corso di laurea in Informatica AA 2009/2010 Violetta Lonati Heap e code di priorità AA 2009/2010 1/16

Problema Contesto S è un insieme dinamico di n elementi, ciascuno dei quali è dotato di una chiave o valore di priorità; in genere: minore è la chiave, massimo è il suo valore di priorità. Le chiavi sono ordinate (totalmente), ovvero per ogni coppia di chiavi k 1 e k 2 si ha k 1 k 2 oppure k 2 k 1. Vogliamo poter eseguire efficientemente le seguenti operazioni: inserire elementi; scegliere l elemento di S con massima priorità (valore minimo); cancellare l elemento di S con massima priorità. Esempio di applicazione Scheduling online di processi (ad opera del sistema operativo): i processi vanno eseguiti in base ad un certo valore di priorità, ma le richieste non arrivano necessariamente in questo ordine. Violetta Lonati Heap e code di priorità AA 2009/2010 2/16

Ordinamento tramite code di priorità Avendo a disposizione una coda di priorità, è possibile effettuare questo algoritmo di ordinamento: crea una nuova coda di priorità Q inserisci in Q un elemento di S alla volta finchè Q non è vuota estrai il minimo m da Q stampa m Se le operazioni di inserimento e estrazione del minimo si possono fare in tempo O(log n), allora otterremmo un algoritmo di ordinamento ottimale, ovvero di costo O(n log n), infatti: per ogni elemento di S, l inserimento in coda costa O(log n), quindi l inserimento degli n elementi costa O(n log n); l estrazione del minimo costa O(log n) quindi il ciclo finale costa O(n log n). Obiettivo: implementare queste operazioni con costo O(log n)!! Violetta Lonati Heap e code di priorità AA 2009/2010 3/16

Implementazioni naïf (1) Usando una lista con un puntatore all elemento minimo: l inserimento in testa ha costo O(1); la ricerca del minimo ha costo O(1); per estrarre il minimo devo aggiornare il puntatore, quindi devo scorrere la lista e il costo diventa O(n). Soluzione non ottimale Violetta Lonati Heap e code di priorità AA 2009/2010 4/16

Implementazioni naïf (2) Usando una struttura ordinata: la ricerca del minimo ha costo O(1); l estrazione del minimo ha costo O(1); l inserimento ha costo O(n): se uso un array: con una ricerca dicotomica trovo la posizione in cui inserire con costo O(log n) ma poi devo spostare tutti gli elementi più grandi e questo nel caso peggiore ha costo O(n); se uso una lista: l inserimento ha costo O(1), ma la ricerca della posizione in cui effettuarlo ha costo O(n) (devo scorrerre nel caso peggiore tutta la lista). Soluzione non ottimale Violetta Lonati Heap e code di priorità AA 2009/2010 5/16

Struttura dati Heap Uno heap è un albero binario completo (bilanciato) dove le chiavi rispettano questa proprietà: la chiave di un nodo è sempre minore della chiave dei sui figli. per ogni nodo i : key(father(i)) key(i) Violetta Lonati Heap e code di priorità AA 2009/2010 6/16

Rappresentazione di uno heap Uno heap può essere rappresentato in memoria come un albero binario (nodi con puntatori ai figli destro e sinistro). Essendo però un albero completo (tutti i livelli sono riempiti tranne al più l ultimo), è comodo rappresentare uno heap semplicemente con un array. h = {IGNORE, 1, 2, 5, 10, 3, 7, 11, 15, 17, 20, 9, 15, 8, 16} Violetta Lonati Heap e code di priorità AA 2009/2010 7/16

Rappresentazione di uno heap - continua NB: per coerenza con le dispense e il libro riempiamo l array a partire dalla posizione 1 (lasciando inutilizzata la posizione 0). Formalmente: detto n il numero di elementi contenuti nell array, abbiamo: i 1 left(i) = 2i se 2i n i 1 right(i) = 2i + 1 se 2i + 1 n i 2 father(i) = i/2 se 2i + 1 n h = {IGNORE, 1, 2, 5, 10, 3, 7, 11, 15, 17, 20, 9, 15, 8, 16} Violetta Lonati Heap e code di priorità AA 2009/2010 8/16

Ricerca del minimo La ricerca del minimo è immediata: si trova nella radice! Costo O(1) Violetta Lonati Heap e code di priorità AA 2009/2010 9/16

Inserimento Chiamiamo h il vettore che rappresenta lo heap e sia n-1 la sua lunghezza (ovvero il numero di elementi che contiene attualmente). Se inserisco il nuovo elemento nella posizione n di h, la proprietà dello heap potrebbe non essere più valida, perchè in posizione n potrei avere una chiave troppo piccola. Aggiustiamo lo heap a partire dalla posizione n risalendo verso l alto, usando la seguente funzione ricorsiva: void heapify_ up ( Heap h, int i ) { if ( i > 1 ) { int j = father (i); if ( cmp ( key ( h[ i] ), key ( h[ j] ) ) < 0 ) { swap ( h, i, j ); heapify_ up ( h, j ); } } } Chiaramente la funzione father(i) deve restituire l elemento di h in posizione i/2. Violetta Lonati Heap e code di priorità AA 2009/2010 10/16

Inserimento - esempio Violetta Lonati Heap e code di priorità AA 2009/2010 11/16

Inserimento - correttezza e complessità Ad ogni esecuzione di heapify_up(i), riparo il sottoalbero di radice i e risalgo, promuovendo gli elementi di chiave più bassa. Correttezza Se parto da un albero che è quasi uno heap tranne che per il fatto che la chiave di i è troppo piccola, allora la chiamata di heapify_up(h,i) consente di ottenere uno heap corretto. Complessità O(log n): al più effettuo tanti confronti/scambi quanta è l altezza del nodo i nell albero. Violetta Lonati Heap e code di priorità AA 2009/2010 12/16

Cancellazione In genere, una coda di priorità richiede di cancellare solo l elemento di chiave minima. Qui vediamo la cancellazione in generale. Sia n la lunghezza dello heap h; per cancellare l elemento di posizione i: spostiamo h(n) in h(i) e decrementiamo la lunghezza n; la proprietà dello heap non vale più, poichè in posizione i potrei avere una chiave troppo grande; 1. se key(i) < key(father(i), allora aggiusto lo heap verso l alto chiamando heapify_up(h,i) 2. se key(i) > key(left(i) oppure key(i) > key(right(i), allora aggiusto lo heap verso il basso con la funzione ricorsiva heapify_down(h,i,n). Violetta Lonati Heap e code di priorità AA 2009/2010 13/16

Cancellazione void heapify_ down ( Heap h, int i, int n ) { if ( 2* i <= n ) { / i ha almeno un figlio / int j; / indice del figlio di i con chiave minore / if ( 2* i == n ) / i ha solo il figlio sinistro / j = 2* i; else / i ha due figli / j = cmp ( key ( h [2* i] ), key ( h [2* i +1] ) ) < 0? 2* i : 2* i + 1; } } if ( cmp ( key ( h[ j] ), key ( h[ i] ) ) < 0 ) { swap ( h, i, j ); heapify_down ( h, j, n ); } NB: in questo caso serve sapere quanti sono gli elementi contenuti nello heap, quindi serve l argomento n. Violetta Lonati Heap e code di priorità AA 2009/2010 14/16

Cancellazione - esempio Violetta Lonati Heap e code di priorità AA 2009/2010 15/16

Cancellazione - correttezza e complessità Correttezza Se parto da un albero che è quasi uno heap tranne che per il fatto che la chiave di i è troppo grande, allora la chiamata di heapify_down(h,i,n) consente di ottenere uno heap corretto. Complessità O(log n): al più effettuo tanti confronti/scambi quanto è lungo il cammino dal nodo i fino ad una foglia. Violetta Lonati Heap e code di priorità AA 2009/2010 16/16