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