Esercizio
Si scriva un metodo public Position<E> sibling(Position<E> v) che preso
in input un nodo v restituisca il fratello di v. Il metodo dovrà lanciare una
BoundaryViolationException nel caso in cui v non abbia un fratello.
Strutture Dati
Code a Priorità
E` un contenitore di oggetti
ciascun oggetto possiede una chiave (key) che specifica la priorità
dell'oggetto all'interno della collezione
la chiave viene generalmente assegnata a un elemento nel momento in
cui l'elemento viene inserito e può essere successivamente modificata
ad ogni istante può essere rimosso soltanto l'elemento con la più alta
priorità
Strutture Dati
Code a Priorità
Per poter stabilire qual è l'oggetto con la più alta priorità è necessario
definire una regola per confrontare le chiavi
Come deve essere questa regola?
deve rendere possibile il confronto fra ogni coppia di chiavi
deve stabilire un ordine all'interno della collezione
Strutture Dati
Code a Priorità
Relazione d'ordine
è una relazione binaria ≤ su un insieme X che è riflessiva, antisimmetrica e
transitiva.
proprietà riflessiva: k ≤ k
proprietà antisimmetrica: se k ≤ k' e k' ≤ k, allora k = k'
proprietà transitiva: se k' ≤ k'' e k'' ≤ k''', allora k' ≤ k'''
una relazione d'ordine ≤ si dice totale se
k ≤ k' oppure k' ≤ k per ciascuna coppia di elementi k,k' in X
se su una collezione è definita una relazione d'ordine totale, allora è ben
definito il più piccolo valore della collezione (chiave più piccola)
Strutture Dati
Code a Priorità
l'ADT Coda a Priorità è così definito:
E` un contenitore di elementi, ciascun elemento è una coppia
(chiave, valore)
Metodi principali
insert(k,x): inserisce l'elemento con valore x e priorità k
removeMin() (o extractMin()): restituisce e rimuove un elemento con la
più alta priorità, cioè un elemento con chiave minore o uguale di quella di
ogni altro elemento
Strutture Dati
Code a Priorità
Come fare per tenere traccia dell'associazione valore-chiave?
composition pattern: un singolo oggetto (entry) è definito come
composizione di altri oggetti
chiave
valore
public interface Entry<K, V> {
/** Restituisce la chiave memorizzata in questa entry. */
public K getKey();
/** Restituisce il valore memorizzato in questa entry. */
public V getValue();
}
Strutture Dati
Code a Priorità
Come confrontare le chiavi in modo da determinare la più piccola?
Strategia 1
implementare una diversa coda a priorità per ogni tipo di chiave e per
ogni possibile regola di confronto che si vuole usare
Inconveniente: non è molto generale, richiede la riscrittura di molto
codice simile
Strutture Dati
Code a Priorità
Come confrontare le chiavi in modo da determinare la più piccola?
Strategia 2
le chiavi sono istanze di una classe key che definisce il modo con cui
fare il confronto con un opportuno metodo
Inconveniente: non esiste un modo unico per confrontare due chiavi.
Ci sono contesti in cui l'esito del confronto può essere diverso
sulla stessa coppia di chiavi.
Esempio:
chiavi 4 e 11:
4 ≤ 11 se 4 e 11 sono confrontate numericamente;
11 ≤ 4 se 4 e 11 sono confrontate lessicograficamente;
Strutture Dati
Code a Priorità
Come confrontare le chiavi in modo da determinare la più piccola?
comparator pattern: invece di basarci sulle chiavi, per stabilire la regola
di confronto definiamo un oggetto comparator (esterno alle chiavi):
ogni volta che viene costruita una nuova Coda a Priorità, viene fornito un
oggetto Comparator
la Coda a Priorità dà la possibilità di definire un nuovo Comparator se il
precedente diventa obsoleto
Vantaggi: si può dare un'implementazione generale di Coda a Priorità che
funziona in una grande varietà di contesti
Strutture Dati
ADT Coda a Priorità
ADT Comparator
L'ADT Comparator fornisce un meccanismo di confronto basato sul seguente
unico metodo:
int compare(E a, E b): restituisce un intero i tale che:
i < 0 se a < b;
i = 0 se a = b;
i > 0 se a > b.
Si verifica una condizione di errore se a e b
non possono essere confrontati
java.util.comparator è l'interfaccia che definisce l'ADT Comparator
Strutture Dati
ADT Coda a Priorità
ADT Comparator (interfaccia java.util.comparator)
L'interfaccia java.util.comparator
include anche il seguente metodo:
●
equals() : confronta un comparatore con un altro comparatore
Strutture Dati
ADT Coda a Priorità
Elenco completo dei metodi
Metodi generici
● size()
● isEmpty()
●
●
●
●
●
Metodi di accesso
min()
Metodi di modifica
insert(k,x)
removeMin()
Strutture Dati
ADT Coda a Priorità
Eccezioni
●
●
EmptyPriorityQueueException: lanciato se il metodo min o
removeMin viene chiamato su una Coda a Priorità vuota
InvalidKeyException: lanciato se il metodo insert(k,x) viene chiamato
con una chiave k non valida che rende impossibile il confronto con il
Comparator della Coda a Priorità (k null oppure k è di una classe
incompatibile con le classi delle altre chiavi)
Strutture Dati
ADT Coda a Priorità
Interfaccia
public interface PriorityQueue<K, V> {
public int size();
public boolean isEmpty();
/** Restituisce senza rimuoverla una entry con chiave minima. */
public Entry<K,V> min() throws EmptyPriorityQueueException;
/** Inserisce una coppia key-value e restituisce la entry creata. */
public Entry<K,V> insert(K key, V value) throws InvalidKeyException;
/** Rimuove e restituisce una entry con chiave minima. */
public Entry<K,V> removeMin() throws EmptyPriorityQueueException;
}
Strutture Dati
ADT Coda a Priorità
Implementazione con lista non ordinata
Gli elementi (k,x) della Coda a Priorità P sono memorizzati in una lista L
implementata come lista doppiamente concatenata
Caratteristiche: inserimento veloce e cancellazione lenta
insert(k,x) richiede tempo O(1) perché possiamo semplicemente creare
un nuovo oggetto entry e=(k,x) e usare insertLast(e)
min() e removeMin() richiedono tempo O(n) perché richiedono lo
scorrimento della lista (non ordinata) per determinare l'elemento con
chiave minima
Strutture Dati
ADT Coda a Priorità
Implementazione con lista ordinata
Gli elementi (k,x) della Coda a Priorità P sono memorizzati in ordine non
decrescente di chiavi in una lista L implementata come lista doppiamente
concatenata
Caratteristiche: Cancellazione veloce e inserimento lento
insert(k,x) richiede tempo O(n) perché bisogna inserire il nuovo oggetto
entry e=(k,x) nel posto giusto per mantenere l'ordine non decrescente
delle chiavi
min() e removeMin() richiedono tempo O(1) perché la chiave minima è
all'inizio della lista
Strutture Dati
ADT Coda a Priorità
Implementazione con lista ordinata
import java.util.Comparator;
public class DefaultComparator<E> implements Comparator<E> {
public int compare(E a, E b) throws ClassCastException {
return ((Comparable<E>) a).compareTo(b);
}
}
Strutture Dati
ADT Coda a Priorità
Implementazione con lista ordinata
import java.util.Comparator;
import nodelist.*;
import position.*;
public class SortedListPriorityQueue<K,V> implements PriorityQueue<K,V> {
protected PositionList<Entry<K,V>> entries;
protected Comparator<K> c;
/** Classe interna per le entrate della coda a priorita` */
protected static class MyEntry<K,V> implements Entry<K,V> {
protected K k; // chiave
protected V v; // valore
public MyEntry(K key, V value) {
k = key;
v = value;
}
// metodi dell'interfaccia Entry
public K getKey() { return k; }
public V getValue() { return v; }
}
...
}
Strutture Dati
ADT Coda a Priorità
Implementazione con lista ordinata
public class SortedListPriorityQueue<K,V> implements PriorityQueue<K,V> {
...
/** Crea la coda a priorita` con il comparatore di default. */
public SortedListPriorityQueue () {
entries = new NodePositionList<Entry<K,V>>();
c = new DefaultComparator<K>();
}
/** Crea la coda a priorita` con un dato comparatore. */
public SortedListPriorityQueue (Comparator<K> comp) {
entries = new NodePositionList<Entry<K,V>>();
c = comp;
}
/** Crea la coda a priorita` con un dato comparatore e una data lista.
* Si assume che gli elementi della lista siano in ordine non decrescente.*/
public SortedListPriorityQueue (PositionList<Entry<K,V>> list,
Comparator<K> comp) {
entries = list;
c = comp;
}
...
}
Strutture Dati
ADT Coda a Priorità
Implementazione con lista ordinata
public class SortedListPriorityQueue<K,V> implements PriorityQueue<K,V> {
...
/** Setta il comparatore per questa coda a priorita`.
* @throws IllegalStateException se la coda a p. non e` vuota */
public void setComparator(Comparator<K> comp)
throws IllegalStateException {
if(!isEmpty())
throw new IllegalStateException("la coda a priorita` non e`
vuota");
c = comp;
}
public int size () {return entries.size(); }
public boolean isEmpty () { return entries.isEmpty(); }
...
}
Strutture Dati
ADT Coda a Priorità
Implementazione con lista ordinata
public class SortedListPriorityQueue<K,V> implements PriorityQueue<K,V> {
...
/** Determina se una chiave e` valida. */
protected boolean checkKey(K key) throws InvalidKeyException {
boolean result;
try { // controlla se la chiave può essere confrontata con sé stessa
result = (c.compare(key,key)==0);
} catch (ClassCastException e)
{ throw new InvalidKeyException("la chiave non è confrontabile"); }
return result;
}
...
}
Strutture Dati
ADT Coda a Priorità
Implementazione con lista ordinata
public class SortedListPriorityQueue<K,V> implements PriorityQueue<K,V> {
...
protected void insertEntry(Entry<K,V> e) {
for (Position<Entry<K,V>> posentry : entries.positions())
if (c.compare(e.getKey(), posentry.element().getKey()) <= 0){
entries.addBefore(posentry, e);
return;
}
entries.addLast(e);
}
...
}
addBefore
13
5
Strutture Dati
5
11
15
21
22
ADT Coda a Priorità
Implementazione con lista ordinata
public class SortedListPriorityQueue<K,V> implements PriorityQueue<K,V> {
...
protected void insertEntry(Entry<K,V> e) {
for (Position<Entry<K,V>> posentry : entries.positions())
if (c.compare(e.getKey(), posentry.element().getKey()) <= 0){
entries.addBefore(posentry, e);
return;
}
entries.addLast(e);
}
...
}
addLast
28
5
Strutture Dati
5
11
15
21
22
ADT Coda a Priorità
Implementazione con lista ordinata
public class SortedListPriorityQueue<K,V> implements PriorityQueue<K,V> {
...
public Entry<K,V> insert (K k, V v) throws InvalidKeyException {
checkKey(k);//metodo ausiliario per verificare che una chiave sia valida
Entry<K,V> entry = new MyEntry<K,V>(k, v);
insertEntry(entry);
// metodo ausiliario per l'inserimento
return entry;
}
...
}
Strutture Dati
ADT Coda a Priorità
Esercizi
Completare la classe SortedListPriorityQueue con gli altri metodi:
public Entry<K,V> min() throws EmptyPriorityQueueException;
public Entry<K,V> removeMin() throws EmptyPriorityQueueException;
Scrivere una classe UnsortedListPriorityQueue che implementa la Coda a
Priorità con una lista non ordinata
Strutture Dati
Esercizio 1
Scrivere un metodo
static<E> void PriorityQueueSort(PositionList<E> L, Comparator<E> comp)
che prendendo in input una lista di nodi L e un comparatore comp, ordini la
lista usando una coda a priorità.
Strutture Dati
Esercizio 2
Scrivere una classe PQStack<E> che implementi l'interfaccia Stack<E> usando
una coda a priorità
Strutture Dati