aggiunte altre implementazione di coda prioritaria basata su heap
This commit is contained in:
11
src/it/algoritmi/adt/AdaptablePriorityQueue.java
Normal file
11
src/it/algoritmi/adt/AdaptablePriorityQueue.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package it.algoritmi.adt;
|
||||||
|
|
||||||
|
public interface AdaptablePriorityQueue<K extends Comparable<K>, V> extends PriorityQueue<K, V> {
|
||||||
|
|
||||||
|
public void remove(Entry<K, V> entry) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
public void replaceKey(Entry<K, V> entry, K key) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
public void replaceValue(Entry<K, V> entry, V value) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
}
|
||||||
115
src/it/algoritmi/adt/queue/HeapAdaptablePriorityQueue.java
Normal file
115
src/it/algoritmi/adt/queue/HeapAdaptablePriorityQueue.java
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package it.algoritmi.adt.queue;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import it.algoritmi.adt.AdaptablePriorityQueue;
|
||||||
|
import it.algoritmi.adt.Entry;
|
||||||
|
|
||||||
|
public class HeapAdaptablePriorityQueue<K extends Comparable<K>, V> extends HeapPriorityQueue<K, V>
|
||||||
|
implements AdaptablePriorityQueue<K, V> {
|
||||||
|
|
||||||
|
// ---------------- class AdaptablePQEntry annidata ----------------
|
||||||
|
/**
|
||||||
|
* Estensione della classe PQEntry per aggiungere informazioni sulla posizione.
|
||||||
|
*/
|
||||||
|
protected static class AdaptablePQEntry<K extends Comparable<K>, V> extends PQEntry<K, V> {
|
||||||
|
|
||||||
|
private int index; // indice della voce nell'array che realizza lo heap
|
||||||
|
|
||||||
|
public AdaptablePQEntry(K key, V value, int j) {
|
||||||
|
super(key, value);
|
||||||
|
setIndex(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndex(int index) {
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// ---------------- fine della classe AdaptablePQEntry annidata --------
|
||||||
|
|
||||||
|
/** Crea una coda prioritaria flessibile vuota che usa l'ordine naturale. */
|
||||||
|
public HeapAdaptablePriorityQueue() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crea una coda prioritaria flessibile vuota che usa il comparatore fornito.
|
||||||
|
*/
|
||||||
|
public HeapAdaptablePriorityQueue(Comparator<K> comparator) {
|
||||||
|
super(comparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Determina se una voce è valida, controllando la sua posizione. */
|
||||||
|
protected AdaptablePQEntry<K, V> validate(Entry<K, V> entry) throws IllegalArgumentException {
|
||||||
|
if (!(entry instanceof AdaptablePQEntry))
|
||||||
|
throw new IllegalArgumentException("Invalid entry");
|
||||||
|
AdaptablePQEntry<K, V> locator = (AdaptablePQEntry<K, V>) entry; // cast sicuro
|
||||||
|
int j = locator.getIndex();
|
||||||
|
if (j >= heap.size() || heap.get(j) != locator)
|
||||||
|
throw new IllegalArgumentException("Invalid entry");
|
||||||
|
return locator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Scambia tra loro le voci delle celle i e j dell'array. */
|
||||||
|
@Override
|
||||||
|
protected void swap(int i, int j) {
|
||||||
|
super.swap(i, j);
|
||||||
|
((AdaptablePQEntry<K, V>) heap.get(i)).setIndex(i);
|
||||||
|
((AdaptablePQEntry<K, V>) heap.get(j)).setIndex(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Ripristina la priorità di ordinamento spostando la voce j in altro/basso. */
|
||||||
|
protected void bubble(int j) {
|
||||||
|
if (j > 0 && compare(heap.get(j), heap.get(parent(j))) < 0)
|
||||||
|
upheap(j);
|
||||||
|
else
|
||||||
|
downheap(j); // però può darsi che non sia necessario alcuno spostamento
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Inserisce una coppia chiave-valore e restituisce la voce creata. */
|
||||||
|
@Override
|
||||||
|
public Entry<K, V> insert(K key, V value) throws IllegalArgumentException {
|
||||||
|
checkKey(key);
|
||||||
|
Entry<K, V> newest = new AdaptablePQEntry<K, V>(key, value, heap.size());
|
||||||
|
heap.add(newest);
|
||||||
|
upheap(heap.size() - 1);
|
||||||
|
return newest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Elimina dalla coda prioritaria la voce ricevuta. */
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Entry<K, V> entry) throws IllegalArgumentException {
|
||||||
|
AdaptablePQEntry<K, V> locator = validate(entry);
|
||||||
|
int j = locator.getIndex();
|
||||||
|
if (j == heap.size() - 1) // la voce si trova nell'ultima posizione
|
||||||
|
heap.remove(heap.size() - 1); // quindi basta eliminarla
|
||||||
|
else {
|
||||||
|
swap(j, heap.size() - 1);
|
||||||
|
heap.remove(heap.size() - 1);
|
||||||
|
bubble(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sostituisce la chiave di una voce. */
|
||||||
|
@Override
|
||||||
|
public void replaceKey(Entry<K, V> entry, K key) throws IllegalArgumentException {
|
||||||
|
AdaptablePQEntry<K, V> locator = validate(entry);
|
||||||
|
checkKey(key);
|
||||||
|
locator.setKey(key);
|
||||||
|
bubble(locator.getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sostituisce il valore di una voce. */
|
||||||
|
@Override
|
||||||
|
public void replaceValue(Entry<K, V> entry, V value) throws IllegalArgumentException {
|
||||||
|
AdaptablePQEntry<K, V> locator = validate(entry);
|
||||||
|
locator.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
127
src/it/algoritmi/adt/queue/HeapPriorityQueue.java
Normal file
127
src/it/algoritmi/adt/queue/HeapPriorityQueue.java
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
package it.algoritmi.adt.queue;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import it.algoritmi.adt.Entry;
|
||||||
|
|
||||||
|
public class HeapPriorityQueue<K extends Comparable<K>, V> extends AbstractPriorityQueue<K, V> {
|
||||||
|
|
||||||
|
/** Contenitore principale delle voci della coda prioritaria. */
|
||||||
|
protected ArrayList<Entry<K, V>> heap = new ArrayList<>();
|
||||||
|
|
||||||
|
/** Crea una coda prioritaria vuota che usa l'ordine naturale tra le chiavi. */
|
||||||
|
public HeapPriorityQueue() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Crea una coda prioritaria vuota che usa il comparatore fornito. */
|
||||||
|
public HeapPriorityQueue(Comparator<K> comparator) {
|
||||||
|
this.comparator = comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Crea una coda prioritaria contenente le coppie chiave-valore fornite. */
|
||||||
|
public HeapPriorityQueue(K[] keys, V[] values) {
|
||||||
|
super();
|
||||||
|
for (int j = 0; j < Math.min(keys.length, values.length); j++)
|
||||||
|
heap.add(new PQEntry<K, V>(keys[j], values[j]));
|
||||||
|
heapify();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int parent(int j) {
|
||||||
|
return (j - 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int left(int j) {
|
||||||
|
return 2 * j + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int right(int j) {
|
||||||
|
return 2 * j + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hasLeft(int j) {
|
||||||
|
return left(j) < heap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hasRight(int j) {
|
||||||
|
return right(j) < heap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Effettua la costruzione bottom-up dello heap in un tempo lineare. */
|
||||||
|
protected void heapify() {
|
||||||
|
int startIndex = parent(size() - 1); // inizia dal genitore dell'ultima entità
|
||||||
|
for (int j = startIndex; j >= 0; j--)
|
||||||
|
downheap(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Scambia tra loro nella lista le voci di indice i e j. */
|
||||||
|
protected void swap(int i, int j) {
|
||||||
|
Entry<K, V> tmp = heap.get(i);
|
||||||
|
heap.set(i, heap.get(j));
|
||||||
|
heap.set(j, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sposta in alto la voce di indice j, se necessario per l'ordinamento */
|
||||||
|
protected void upheap(int j) {
|
||||||
|
while (j > 0) {
|
||||||
|
int p = parent(j);
|
||||||
|
if (compare(heap.get(j), heap.get(p)) >= 0)
|
||||||
|
break;
|
||||||
|
swap(j, p);
|
||||||
|
j = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sposta in alto la voce di indice j, se necessario per l'ordinamento. */
|
||||||
|
protected void downheap(int j) {
|
||||||
|
while (hasLeft(j)) { // prosegue verso il basso (o fino a break)
|
||||||
|
int leftIndex = left(j);
|
||||||
|
int smallChildIndex = leftIndex; // il destro può essere minore
|
||||||
|
if (hasRight(j)) {
|
||||||
|
int rightIndex = right(j);
|
||||||
|
if (compare(heap.get(leftIndex), heap.get(rightIndex)) > 0)
|
||||||
|
smallChildIndex = rightIndex; // il figlio destro è minore
|
||||||
|
}
|
||||||
|
if (compare(heap.get(smallChildIndex), heap.get(j)) >= 0)
|
||||||
|
break; // ordinamento corretto
|
||||||
|
swap(j, smallChildIndex);
|
||||||
|
j = smallChildIndex; // prosegue dalla posizione del figlio prescelto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Restituisce il numero di voci presenti nella coda prioritaria. */
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return heap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Inserisce una coppia chiave-valore e restituisce la voce creata. */
|
||||||
|
@Override
|
||||||
|
public Entry<K, V> insert(K key, V value) throws IllegalArgumentException {
|
||||||
|
checkKey(key); // metodo ausiliario di verifica (può lanciare eccezione)
|
||||||
|
Entry<K, V> newest = new PQEntry<>(key, value);
|
||||||
|
heap.add(newest); // aggiunge alla fine della lista
|
||||||
|
upheap(heap.size() - 1); // esegue up-heap per la voce appena aggiunta
|
||||||
|
return newest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Restituisce una della voci aventi chiave minima (senza rimuoverla). */
|
||||||
|
@Override
|
||||||
|
public Entry<K, V> min() {
|
||||||
|
if (heap.isEmpty()) return null;
|
||||||
|
return heap.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Elimina e restituisce una delle voci aventi chiave minima. */
|
||||||
|
@Override
|
||||||
|
public Entry<K, V> removeMin() {
|
||||||
|
if (heap.isEmpty()) return null;
|
||||||
|
Entry<K, V> answer = heap.get(0);
|
||||||
|
swap(0, heap.size() - 1); // sposta l'elemento minimo alla fine
|
||||||
|
heap.remove(heap.size() - 1); // e lo rimuove dall lista
|
||||||
|
downheap(0); // quindi sistema la radice con down-heap
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user