initial commit

This commit is contained in:
Fabio Scotto di Santolo
2018-02-20 11:37:37 +01:00
commit 988025618b
33 changed files with 1901 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
package it.algoritmi.adt;
public interface CircularQueue<E> extends Queue<E> {
/**
* Sposta alla fine della coda il suo elemento iniziale.
* Se la coda <20> vuota non fa niente.
*/
void rotate();
}

View File

@@ -0,0 +1,33 @@
package it.algoritmi.adt;
/**
* Interfaccia che definisce una coda doppia: un contenitore di elementi con
* inserimenti e rimozioni ai due estremi. Semplificata rispetto a java.util.Dequeue.
*/
public interface Deque<E> {
/** Restituisce il numero di elementi presenti nella coda doppia. */
int size();
/** Verifica se la coda doppia <20> vuota. */
boolean isEmpty();
/** Restituisce il primo elemento, senza toglierlo (null se la coda <20> vuota). */
E first();
/** Restituisce l'ultimo elemento, senza toglierlo (null se la coda <20> vuota). */
E last();
/** Inserisce un elemento all'inizio della coda doppia. */
void addFirst(E e);
/** Inserisce un elemento alla fine della coda doppia. */
void addLast(E e);
/** Elimina e restituisce il primo elemento della coda (null se <20> vuota). */
E removeFirst();
/** Elimina e restituisce l'ultimo elemento della coda (null se <20> vuota). */
E removeLast();
}

View File

@@ -0,0 +1,24 @@
package it.algoritmi.adt;
/** Una versione semplificata dell'interfaccia java.util.List. */
public interface List<E> extends Iterable<E> {
/** Restituisce il numero di elementi presenti nella lista. */
int size();
/** Restituisce true se e sole se la lista è vuota. */
boolean isEmpty();
/** Restituisce l'elemento corristondente all'indice i, senza eliminarlo. */
E get(int i) throws IndexOutOfBoundsException;
/** Sostituisce con e l'elemento di indice i; restituisce l'elemento sostituito. */
E set(int i, E e) throws IndexOutOfBoundsException;
/** Inserisce e come elemento di indice i, spostando gli elementi successivi. */
void add(int i, E e) throws IndexOutOfBoundsException;
/** Rimuove e restituisce l'elemento di indice i, spostando i successivi. */
E remove(int i) throws IndexOutOfBoundsException;
}

View File

@@ -0,0 +1,13 @@
package it.algoritmi.adt;
public interface Position<E> {
/**
* Restituisce l'elemento memorizzato in questa posizione.
*
* @return l'elemento memorizzato
* @throws IllegalStateException se la posizione non è più valida
*/
E getElement() throws IllegalStateException;
}

View File

@@ -0,0 +1,45 @@
package it.algoritmi.adt;
/** L'interfaccia che definisce liste posizionali. */
public interface PositionalList<E> extends Iterable<E> {
/** Restituisce il numero di elementi presenti nella lista. */
int size();
/** Restituisce true se e solo se la lista è vuota. */
boolean isEmpty();
/** Restituisce la prima Position della lista (o null se la lista è vuota). */
Position<E> first();
/** Restituisce l'ultima Position della lista (o null se la lista è vuota). */
Position<E> last();
/** Restituisce la Position che precede p (o null, se p è la prima). */
Position<E> before(Position<E> position) throws IllegalArgumentException;
/** Restituisce la Position che segue p (o null, se p è l'ultima). */
Position<E> after(Position<E> position) throws IllegalArgumentException;
/** Inserisce l'elemento e all'inizio della lista; ne restituisce la posizione. */
Position<E> addFirst(E element);
/** Inserisce l'elemento e alla fine della lista; ne restituisce la posizione. */
Position<E> addLast(E element);
/** Inserisce l'elemento e prima della Position p; ne restituisce la posizione. */
Position<E> addBefore(Position<E> position, E element) throws IllegalArgumentException;
/** Inserisce l'elemento e dopo la Position p; ne restituisce la posizione. */
Position<E> addAfter(Position<E> position, E element) throws IllegalArgumentException;
/** Sostituisce l'elemento nella Position p; restituisce l'elemento sostituito. */
E set(Position<E> position, E element) throws IllegalArgumentException;
/** Elimina e restituisce l'elemento nella Position p; (poi p non è più valida). */
E remove(Position<E> position) throws IllegalArgumentException;
/** Restituisce una rappresentazione iterabile delle posizioni dela lista. */
public Iterable<Position<E>> positions();
}

View File

@@ -0,0 +1,20 @@
package it.algoritmi.adt;
public interface Queue<E> {
/** Restituisce il numero di elementi presenti nella coda. */
public int size();
/** Verifica se la coda <20> vuota. */
public boolean isEmpty();
/** Inserisce un elemento in fondo alla coda. */
public void enqueue(E e);
/** Elimina e restituisce il primo elemento della coda (null se <20> vuota). */
public E dequeue();
/** Restituisce il primo elemento della coda, senza toglierlo (null se <20> vuota). */
public E first();
}

View File

@@ -0,0 +1,44 @@
package it.algoritmi.adt;
/**
* Una raccolta di oggetti che vengono inseriti e eliminati secondo il principio
* last-in first-out. Anche se ha uno scopo simile, questa interfaccia <20> diversa da
* java.util.Stack
*
* @author fscotto
*
*/
public interface Stack<E> {
/**
* Restituisce il numero di elementi presenti nella pila.
* @return il numero di elementi presenti nella pila.
*/
int size();
/**
* Verifica se la pila <20> vuota.
* @return true se e solo se la pila <20> vuota
*/
boolean isEmpty();
/**
* Inserisce un elemento in cima alla pila.
* @param e l'elemento da inserire
*/
void push(E e);
/**
* Restituisce l'elemento in cima alla pila, senza eliminarlo.
* @return l'elemento in cima alla pila (o null se la pila <20> vuota)
*/
E top();
/**
* Elimina e restituisce l'elemento che si trova in cima alla pila.
* @return l'elemento eliminato (o null se la pila <20> vuota)
*/
E pop();
}

View File

@@ -0,0 +1,82 @@
package it.algoritmi.adt.dequeue;
import it.algoritmi.adt.Deque;
public class ArrayDeque<E> implements Deque<E> {
private E[] data;
private int size;
private int f;
public static final int CAPACITY = 1000;
public ArrayDeque() {
this(CAPACITY);
}
@SuppressWarnings({"all"})
public ArrayDeque(int capacity) {
data = (E[]) new Object[capacity];
size = 0;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public E first() {
if(isEmpty()) {
return null;
}
return data[f];
}
@Override
public E last() {
if(isEmpty()) {
return null;
}
return data[size-1];
}
@Override
public void addFirst(E element) throws IllegalStateException {
final int len = data.length;
if (size() == len) {
throw new IllegalStateException("Queue is full");
}
final int avail = (f - 1 + len) % len;
data[avail] = element;
++size;
}
@Override
public void addLast(E element) throws IllegalStateException {
final int len = data.length;
if (size() == len) {
throw new IllegalStateException("Queue is full");
}
final int avail = (f + size) % len;
data[avail] = element;
++size;
}
@Override
public E removeFirst() {
// TODO Auto-generated method stub
return null;
}
@Override
public E removeLast() {
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -0,0 +1,49 @@
package it.algoritmi.adt.dequeue;
import it.algoritmi.adt.Deque;
import it.algoritmi.adt.list.DoublyLinkedList;
public class LinkedDeque<E> implements Deque<E> {
private DoublyLinkedList<E> l = new DoublyLinkedList<>();
@Override
public int size() {
return l.size();
}
@Override
public boolean isEmpty() {
return l.isEmpty();
}
@Override
public E first() {
return l.first();
}
@Override
public E last() {
return l.last();
}
@Override
public void addFirst(E element) {
l.addFirst(element);
}
@Override
public void addLast(E element) {
l.addLast(element);
}
@Override
public E removeFirst() {
return l.removeFirst();
}
@Override
public E removeLast() {
return l.removeLast();
}
}

View File

@@ -0,0 +1,161 @@
package it.algoritmi.adt.list;
import java.util.Iterator;
import java.util.NoSuchElementException;
import it.algoritmi.adt.List;
public class ArrayList<E> implements List<E> {
// variabili di esemplare
public static final int CAPACITY = 16; // capacità predefinita dell'array
private E[] data; // array generico per memorizzare gli elementi
private int size; // numero di elementi nella lista
/**
* Costruttore di una lista standard
*/
public ArrayList() {
this(CAPACITY);
}
/**
* Costruisce una lista con capacità data
* @param capacity
*/
@SuppressWarnings("unchecked")
public ArrayList(int capacity) {
data = (E[]) new Object[capacity];
size = 0;
}
/**
* Restituisce il numero di elementi presenti nella lista.
*/
@Override
public int size() {
return size;
}
/**
* Restituisce true se e solo se la lista è vuota.
*/
@Override
public boolean isEmpty() {
return size() == 0;
}
/**
* Restituisce l'elemento corrispondente all'indice i,
* senza eliminarlo.
*/
@Override
public E get(int i) throws IndexOutOfBoundsException {
checkIndex(i, size);
return data[i];
}
/**
* Sostituisce con e l'elemento di indice i;
* restituisce l'elemento sostituito.
*/
@Override
public E set(int i, E e) throws IndexOutOfBoundsException {
checkIndex(i, size);
E tmp = data[i];
data[i] = e;
return tmp;
}
/**
* Inserisce e come elemento di indice i,
* spostando gli elementi successivi.
*/
@Override
public void add(int i, E e) throws IndexOutOfBoundsException {
checkIndex(i, size + 1);
if(size == data.length) resize(2 * data.length);
for(int k = size - 1; k >= i; --k) data[k + 1] = data[k];
data[i] = e;
++size;
}
/**
* Elimina e restituisce l'elemento con l'indice i,
* spostando i successivi.
*/
@Override
public E remove(int i) throws IndexOutOfBoundsException {
checkIndex(i, size);
E tmp = data[i];
for(int k = i; k <= size-1; ++k) data[k] = data[k + 1];
data[size - 1] = null;
--size;
return tmp;
}
/**
* Controlla se l'indice data appartiene all'intervallo [0, n - 1]
* @param i
* @param n
* @throws IndexOutOfBoundsException
*/
protected void checkIndex(int i, int n) throws IndexOutOfBoundsException {
if(i < 0 || i >= n) throw new IndexOutOfBoundsException("Illegal index: " + i);
}
/**
* Ridimensiona l'array interno in modo che abbia capacità >= size.
*/
@SuppressWarnings("unchecked")
protected void resize(int capacity) {
E[] tmp = (E[]) new Object[capacity];
for(int k = 0; k < size; ++k) tmp[k] = data[k];
data = tmp;
}
private class ArrayIterator implements Iterator<E> {
private int j = 0; // indice del prossimo elemento da restituire
private boolean removable = false; // si può invocare remove ora?
/**
* Verifica se l'iteratore ha ancora oggetti da restituire
* @return true se e solo se ci sono ancora oggetti da restituire
*/
@Override
public boolean hasNext() {
return j < size();
}
/**
* Restituisce l'oggetto successivo presente nell'iteratore.
*
* @return l'oggetto successivo
* @throws NoSuchElementException
*/
@Override
public E next() throws NoSuchElementException {
if(j == size()) throw new NoSuchElementException("No next element");
removable = true; // questo elemento potrà poi essere rimosso
return data[j++]; // post-incremente di j, così è pronto per il futuro
}
/**
* Elimina l'elemento restituito dalla più recente invocazione di next.
* @throws IllegalStateException se next non è mai stato invocato
* @throws IllegalStateException se remove è già stato invocato dopo next
*/
@Override
public void remove() throws IllegalStateException {
if(!removable) throw new IllegalStateException("nothing to remove");
ArrayList.this.remove(j-1);
--j;
removable = false;
}
}
@Override
public Iterator<E> iterator() {
return new ArrayIterator();
}
}

View File

@@ -0,0 +1,86 @@
package it.algoritmi.adt.list;
public class CircularyLinkedList<E> {
private Node<E> tail = null;
private int size = 0;
private static class Node<E> {
private E element;
private Node<E> next;
public Node(E e, Node<E> n) {
element = e;
next = n;
}
public E getElement() {
return element;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> n) {
next = n;
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public E first() {
if (isEmpty()) {
return null;
}
return tail.getNext().getElement();
}
public E last() {
if(isEmpty()) {
return null;
}
return tail.getElement();
}
public void rotate() {
if (tail != null) {
tail = tail.getNext();
}
}
public void addFirst(E e) {
if(size == 0) {
tail = new Node<>(e, null);
tail.setNext(tail);
} else {
Node<E> newest = new Node<>(e, tail.getNext());
tail.setNext(newest);
}
size++;
}
public void addLast(E e) {
addFirst(e);
tail = tail.getNext();
}
public E removeFirst() {
if (isEmpty()) {
return null;
}
Node<E> head = tail.getNext();
if(head == tail) {
tail = null;
} else {
tail.setNext(head.getNext());
}
size--;
return head.getElement();
}
}

View File

@@ -0,0 +1,120 @@
package it.algoritmi.adt.list;
public class DoublyLinkedList<E> {
private Node<E> header;
private Node<E> trailer;
private int size = 0;
private static class Node<E> {
private E element;
private Node<E> prev;
private Node<E> next;
private Node(E e, Node<E> prev, Node<E> next) {
element = e;
this.prev = prev;
this.next = next;
}
public Node<E> getPrev() {
return prev;
}
public void setPrev(Node<E> prev) {
this.prev = prev;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> next) {
this.next = next;
}
public E getElement() {
return element;
}
}
public DoublyLinkedList() {
header = new Node<>(null, null, null);
trailer = new Node<>(null, header, null);
header.setNext(trailer);
}
/**
* Restituisce il numero di elementi presenti nella lista
*/
public int size() {
return size;
}
/** Restituisce true se e solo se la lista <20> vuota */
public boolean isEmpty() {
return size == 0;
}
/** Restituisce il primo elemento della lista, senza eliminarlo. */
public E first() {
if(isEmpty()) {
return null;
}
return header.getNext().getElement();
}
/** Restituisce l'ultimo elemento della lista, senza eliminarlo. */
public E last() {
if(isEmpty()) {
return null;
}
return trailer.getPrev().getElement();
}
/** Aggiunge un elemento all'inizio della lista. */
public void addFirst(E e) {
addBetween(e, header, header.getNext());
}
/** Aggiunge un elemento alla fine della lista. */
public void addLast(E e) {
addBetween(e, trailer.getPrev(), trailer);
}
/** Elimina e restituisce il primo elemento della lista. */
public E removeFirst() {
if (isEmpty()) {
return null;
}
return remove(header.getNext());
}
/** Elimina e restituisce l'ultimo elemento della lista. */
public E removeLast() {
if (isEmpty()) {
return null;
}
return remove(trailer.getPrev());
}
/** Elimina dall lista il nodo indicato e restituisce il suo elemento. */
private E remove(Node<E> node) {
Node<E> predecessor = node.getPrev();
Node<E> successor = node.getNext();
predecessor.setNext(successor);
successor.setPrev(predecessor);
--size;
return node.getElement();
}
/** Aggiunge l'elemento e alla lista, tra i due nodi dati. */
private void addBetween(E e, Node<E> predecessor, Node<E> successor) {
// crea un nuovo nodo e lo collega alla lista
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
++size;
}
}

View File

@@ -0,0 +1,111 @@
package it.algoritmi.adt.list;
import java.util.Iterator;
import it.algoritmi.adt.Position;
import it.algoritmi.adt.PositionalList;
/** Gestisce una lista di elementi ordinati in base alla frequenza di accesso. */
public class FavoritesList<E> {
protected static class Item<E> {
private E value;
private int count;
public Item(E value) {
this.value = value;
this.count = 0;
}
public E getValue() {
return value;
}
public int getCount() {
return count;
}
public void increment() {
++this.count;
}
}
PositionalList<Item<E>> list = new LinkedPositionalList<>(); // lista di oggetti
/** Abbreviazione per accedere al preferito memorizzato in posizione position. */
protected E value(Position<Item<E>> position) {
return position.getElement().getValue();
}
/** Abbreviazione per accedere al conteggio associato alla posizione position. */
protected int count(Position<Item<E>> position) {
return position.getElement().getCount();
}
/** Restituisce la Position che ha value uguale a element (o null se non trovato). */
protected Position<Item<E>> findPosition(E element) {
Position<Item<E>> walk = list.first();
while(walk != null && !element.equals(value(walk)))
walk = list.after(walk);
return walk;
}
/** Sposta verso sinistra l'oggetto in posizione position sulla base del conteggio. */
private void moveUp(Position<Item<E>> position) {
int cnt = count(position); // conteggio aggiornato dell'elemento a cui si è acceduto
Position<Item<E>> walk = position;
while (walk != list.first() && count(list.before(walk)) < cnt)
walk = list.before(walk); // trovato un conteggio minore a sinistra
if(walk != position) list.addBefore(walk, list.remove(position)); // elimina e reinserisce l'oggetto
}
/**
* Restituisce il numero di elementi presenti
* nella lista dei preferiti.
*/
public int size() {
return list.size();
}
/**
* Restituisce true se e solo se la lista
* dei preferiti è vuota.
*/
public boolean isEmpty() {
return list.isEmpty();
}
/**
* Accede all'elemento element (eventualmente nuovo),
* incrementando il suo conteggio.
*/
public void access(E element) {
Position<Item<E>> position = findPosition(element); // cerca un elemento esistente
if(position == null) position = list.addLast(new Item<E>(element)); // se nuovo, aggiunge alla fine
position.getElement().increment(); // in ogni caso, incrementa il conteggio
moveUp(position); // sposta a sinistra, se serve
}
/**
* Elimina dalla lista dei preferiti l'elemento
* uguale a element (se c'è).
*/
public void remove(E element) {
Position<Item<E>> position = findPosition(element); // cerca un elemento esitente
if (position != null) list.remove(position);
}
/**
* Restituisce un contenitore iterabile con i k elementi
* aventi più accessi.
*/
public Iterable<E> getFavorites(int k) throws IllegalArgumentException {
if(k < 0 || k > size()) throw new IllegalArgumentException("Invalid k");
PositionalList<E> result = new LinkedPositionalList<>();
Iterator<Item<E>> iter = list.iterator();
for(int j = 0; j < k; ++j) result.addLast(iter.next().getValue());
return result;
}
}

View File

@@ -0,0 +1,46 @@
package it.algoritmi.adt.list;
import it.algoritmi.adt.Position;
import it.algoritmi.adt.PositionalList;
/** Gestisce una lista di preferiti usando l'euristica move-to-front */
public class FavoritesListMTF<E> extends FavoritesList<E> {
/**
* Sposta all'inizio della lista l'oggetto in posizione position
* a cui si è acceduto.
*/
protected void moveUp(Position<Item<E>> position) {
if(position != list.first()) list.addFirst(list.remove(position)); // elimina e reinserisce all'inizio
}
/**
* Restituisce un contenitore iterabile con i k elementi
* aventi più accessi.
*/
@Override
public Iterable<E> getFavorites(int k) throws IllegalArgumentException {
if(k < 0 || k > size()) throw new IllegalArgumentException();
// iniziamo facendo una copia della lista originale
PositionalList<Item<E>> tmp = new LinkedPositionalList<>();
for(Item<E> item : list) tmp.addLast(item);
// cerchiamo ed eliminiamo ripetutamente l'elemento con il conteggio massimo
PositionalList<E> result = new LinkedPositionalList<>();
for(int j = 0; j < k; ++j) {
Position<Item<E>> highPos = tmp.first();
Position<Item<E>> walk = tmp.after(highPos);
while(walk != null) {
if(count(walk) > count(highPos))
highPos = walk;
walk = tmp.after(walk);
}
// abbiamo trovato l'elemento con il conteggio massimo
result.addLast(value(highPos));
tmp.remove(highPos);
}
return result;
}
}

View File

@@ -0,0 +1,303 @@
package it.algoritmi.adt.list;
import java.util.Iterator;
import java.util.NoSuchElementException;
import it.algoritmi.adt.Position;
import it.algoritmi.adt.PositionalList;
/** Implementazione di lista posizionale mediante lista doppiamente concatenata. */
public class LinkedPositionalList<E> implements PositionalList<E> {
private static class Node<E> implements Position<E> {
private E element; // riferimento all'elemento memorizzato in questo nodo
private Node<E> prev; // riferimento al nodo precedente nella lista
private Node<E> next; // riferimento al nodo seguente nella lista
public Node(E element, Node<E> prev, Node<E> next) {
this.element = element;
this.prev = prev;
this.next = next;
}
public Node<E> getPrev() {
return prev;
}
public void setPrev(Node<E> prev) {
this.prev = prev;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> next) {
this.next = next;
}
public void setElement(E element) {
this.element = element;
}
@Override
public E getElement() throws IllegalStateException {
if(next == null) throw new IllegalStateException("Position no longer valid");
return element;
}
}
private Node<E> header; // sentinella iniziale
private Node<E> trailer; // sentinella finale
private int size; // numero di elementi presenti nella lista
public LinkedPositionalList() {
header = new Node<>(null, null, null); // crea la sentinella iniziale
trailer = new Node<>(null, header, null); // trailer è preceduto da header
header.setNext(trailer);
}
/**
* Verifica se la posizione è valida e la restituisce
* sotto forma di nodo.
*
* @param position
* @return
* @throws IllegalArgumentException
*/
private Node<E> validate(Position<E> position) throws IllegalArgumentException {
if(!(position instanceof Node)) throw new IllegalArgumentException("Invalid p");
Node<E> node = (Node<E>) position; // cast sicuro
if(node.getNext() == null) throw new IllegalArgumentException("p is no longer in the list");
return node;
}
/**
* Restituisce il nodo sotto forma di Position (o null, se è una sentinella).
* @param node
* @return
*/
private Position<E> position(Node<E> node) {
return (node != header && node != trailer) ? node : null;
}
/**
* Restituisce il numero di elementi presenti
* nella lista concatenata.
*/
@Override
public int size() {
return size;
}
/**
* Restituisce true se e solo se la lista concatenata è vuota.
*/
@Override
public boolean isEmpty() {
return size() == 0;
}
/**
* Restituisce la prima Position della lista (o null, se la lista è vuota).
*/
@Override
public Position<E> first() {
return position(header.getNext());
}
/**
* Restituisce l'ultima Position della lista(o null, se la lista è vuota).
*/
@Override
public Position<E> last() {
return position(trailer.getPrev());
}
/**
* Restituisce la Position che precede p (o null, se p è la prima).
*/
@Override
public Position<E> before(Position<E> position) throws IllegalArgumentException {
Node<E> node = validate(position);
return position(node.getPrev());
}
/**
* Restituisce la Posizione che segue p (o null, se p è l'ultima).
*/
@Override
public Position<E> after(Position<E> position) throws IllegalArgumentException {
Node<E> node = validate(position);
return position(node.getNext());
}
/**
* Aggiunge l'elemento e alla lista concatenata
* tra i due nodi dati.
*
* @param element
* @param pred
* @param succ
* @return
*/
private Position<E> addBeetween(E element, Node<E> pred, Node<E> succ) {
Node<E> newest = new Node<>(element, pred, succ);
pred.setNext(newest);
succ.setPrev(newest);
++size;
return newest;
}
/**
* Inserisce l'elemento e all'inizio della lista;
* ne restituisce la posizione.
*/
@Override
public Position<E> addFirst(E element) {
return addBeetween(element, header, header.getNext());
}
/**
* Inserisce l'elemento e alla fine della lista;
* ne restituisce la posizione.
*/
@Override
public Position<E> addLast(E element) {
return addBeetween(element, trailer.getPrev(), trailer);
}
/**
* Inserisce l'elemento e prima della Position p;
* ne restituisce la posizione.
*/
@Override
public Position<E> addBefore(Position<E> position, E element) throws IllegalArgumentException {
Node<E> node = validate(position);
return addBeetween(element, node.getPrev(), node);
}
/**
* Inserisce l'elemento e dopo la Position p;
* ne restituisce la posizione.
*/
@Override
public Position<E> addAfter(Position<E> position, E element) throws IllegalArgumentException {
Node<E> node = validate(position);
return addBeetween(element, node, node.getNext());
}
/**
* Sostituisce l'elemento nella Position p;
* restituisce l'elemento sostituito.
*/
@Override
public E set(Position<E> position, E element) throws IllegalArgumentException {
Node<E> node = validate(position);
E answer = node.getElement();
node.setElement(element);
return answer;
}
/**
* Elimina e restituisce l'elemento nella Position p (poi p non è più valida).
*/
@Override
public E remove(Position<E> position) throws IllegalArgumentException {
Node<E> node = validate(position);
Node<E> predecessor = node.getPrev();
Node<E> successor = node.getNext();
predecessor.setNext(successor);
successor.setPrev(predecessor);
--size;
E answer = node.getElement();
node.setElement(null);
node.setNext(null);
node.setPrev(null);
return answer;
}
private class PositionIterator implements Iterator<Position<E>> {
private Position<E> cursor = first(); // prossima posizione da restituire
private Position<E> recent = null; // posizione restituita più recente
/**
* Verifica se l'iteratore ha altro da restituire.
*/
@Override
public boolean hasNext() {
return cursor != null;
}
/**
* Restituisce la prossima posizione dell'iteratore.
*/
@Override
public Position<E> next() throws NoSuchElementException {
if(cursor == null) throw new NoSuchElementException("nothing left");
recent = cursor;
cursor = after(cursor);
return recent;
}
/**
* Elimina l'elemento restituito dalla più recente invocazione di next.
*/
@Override
public void remove() throws IllegalStateException {
if(recent == null) throw new IllegalArgumentException("nothing to remove");
LinkedPositionalList.this.remove(recent); // rimuova l'elemento della lista
recent = null; // non si può invocare di nuovo remove prima di next
}
}
private class PositionIterable implements Iterable<Position<E>> {
@Override
public Iterator<Position<E>> iterator() {
return new PositionIterator();
}
}
/**
* Restituisce una rappresentazione iterabile delle posizioni dela lista.
*/
@Override
public Iterable<Position<E>> positions() {
return new PositionIterable(); // crea un nuovo esemplare della classe interna
}
/**
* Adatta l'iteratore restituito da positions() perchè restituisca elementi.
*/
private class ElementIterator implements Iterator<E> {
Iterator<Position<E>> it = new PositionIterator();
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public E next() {
return it.next().getElement();
}
@Override
public void remove() {
it.remove();
}
}
/**
* Restituisce un iteratore degli elementi memorizzati nella lista.
*/
@Override
public Iterator<E> iterator() {
return new ElementIterator();
}
}

View File

@@ -0,0 +1,123 @@
package it.algoritmi.adt.list;
public class SinglyLinkedList<E> implements Cloneable {
private Node<E> head = null;
private Node<E> tail = null;
private int size = 0;
private static class Node<E> {
private E element;
private Node<E> next;
public Node(E e, Node<E> n) {
element = e;
next = n;
}
public E getElement() {
return element;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> n) {
next = n;
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public E first() {
if(isEmpty()) {
return null;
}
return head.getElement();
}
public E last() {
if (isEmpty()) {
return null;
}
return tail.getElement();
}
public void addFirst(E e) {
head = new Node<>(e, head);
if(size == 0) {
tail = head;
}
size++;
}
public void addLast(E e) {
Node<E> newest = new Node<>(e, null);
if(isEmpty()) {
head = newest;
} else {
tail.setNext(newest);
}
tail = newest;
size++;
}
public E removeFirst() {
if (isEmpty()) {
return null;
}
E answer = head.getElement();
head = head.getNext();
size--;
if (size == 0) {
tail = null;
}
return answer;
}
@Override
@SuppressWarnings("rawtypes")
public boolean equals(Object obj) {
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SinglyLinkedList other = (SinglyLinkedList) obj;
if (size != other.size)
return false;
Node walkA = head;
Node walkB = other.head;
while(walkA != null) {
if (!walkA.getElement().equals(walkB.getElement()))
return false;
walkA = walkA.getNext();
walkB = walkB.getNext();
}
return true;
}
@Override
@SuppressWarnings("unchecked")
public SinglyLinkedList<E> clone() throws CloneNotSupportedException {
SinglyLinkedList<E> other = (SinglyLinkedList<E>) super.clone();
if (size > 0) {
other.head = new Node<>(head.getElement(), null);
Node<E> walk = head.getNext();
Node<E> otherTail = other.head;
while(walk != null) {
Node<E> newest = new Node<>(walk.getElement(), null);
otherTail.setNext(newest);
otherTail = newest;
walk = walk.getNext();
}
}
return other;
}
}

View File

@@ -0,0 +1,62 @@
package it.algoritmi.adt.queue;
import it.algoritmi.adt.Queue;
public class ArrayQueue<E> implements Queue<E> {
public static final int CAPACITY = 1000;
private E[] data;
private int size;
private int f;
public ArrayQueue() {
this(CAPACITY);
}
@SuppressWarnings("unchecked")
public ArrayQueue(int capacity) {
data = (E[]) new Object[capacity];
size = 0;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void enqueue(E element) throws IllegalStateException {
if (size() == data.length) {
throw new IllegalStateException("Queue is full");
}
int avail = (f + size) % data.length;
data[avail] = element;
++size;
}
@Override
public E dequeue() {
if(isEmpty()) {
return null;
}
E answer = data[f];
data[f] = null;
f = (f + 1) % data.length;
--size;
return answer;
}
@Override
public E first() {
if(isEmpty()) {
return null;
}
return data[f];
}
}

View File

@@ -0,0 +1,35 @@
package it.algoritmi.adt.queue;
import it.algoritmi.adt.Deque;
import it.algoritmi.adt.Queue;
import it.algoritmi.adt.dequeue.LinkedDeque;
public class DoubleLinkedQueue<E> implements Queue<E> {
private Deque<E> d = new LinkedDeque<>();
@Override
public int size() {
return d.size();
}
@Override
public boolean isEmpty() {
return d.isEmpty();
}
@Override
public void enqueue(E element) {
d.addFirst(element);
}
@Override
public E dequeue() {
return d.removeLast();
}
@Override
public E first() {
return d.first();
}
}

View File

@@ -0,0 +1,14 @@
package it.algoritmi.adt.queue;
import it.algoritmi.adt.CircularQueue;
import it.algoritmi.adt.list.CircularyLinkedList;
public class LinkedCircularQueue<E> extends LinkedQueue<E> implements CircularQueue<E> {
private CircularyLinkedList<E> list = new CircularyLinkedList<>();
@Override
public void rotate() {
list.rotate();
}
}

View File

@@ -0,0 +1,34 @@
package it.algoritmi.adt.queue;
import it.algoritmi.adt.Queue;
import it.algoritmi.adt.list.SinglyLinkedList;
public class LinkedQueue<E> implements Queue<E> {
private SinglyLinkedList<E> list = new SinglyLinkedList<>();
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void enqueue(E element) {
list.addLast(element);
}
@Override
public E dequeue() {
return list.removeFirst();
}
@Override
public E first() {
return list.first();
}
}

View File

@@ -0,0 +1,56 @@
package it.algoritmi.adt.stack;
import it.algoritmi.adt.Stack;
public class ArrayStack<E> implements Stack<E> {
public static final int CAPACITY = 1000;
private E[] data;
private int t = -1;
public ArrayStack() {
this(CAPACITY);
}
@SuppressWarnings("unchecked")
public ArrayStack(int capacity) {
data = (E[]) new Object[capacity];
}
@Override
public int size() {
return t + 1;
}
@Override
public boolean isEmpty() {
return t == -1;
}
@Override
public void push(E element) throws IllegalStateException {
if (size() == data.length) {
throw new IllegalStateException("Stack is full");
}
data[++t] = element;
}
@Override
public E top() {
if(isEmpty()) {
return null;
}
return data[t];
}
@Override
public E pop() {
if(isEmpty()) {
return null;
}
E answer = data[t];
data[t] = null;
t--;
return answer;
}
}

View File

@@ -0,0 +1,35 @@
package it.algoritmi.adt.stack;
import it.algoritmi.adt.Deque;
import it.algoritmi.adt.Stack;
import it.algoritmi.adt.dequeue.LinkedDeque;
public class DoubledLinkedStack<E> implements Stack<E> {
private Deque<E> d = new LinkedDeque<>();
@Override
public int size() {
return d.size();
}
@Override
public boolean isEmpty() {
return d.isEmpty();
}
@Override
public void push(E element) {
d.addFirst(element);
}
@Override
public E top() {
return d.first();
}
@Override
public E pop() {
return d.removeFirst();
}
}

View File

@@ -0,0 +1,34 @@
package it.algoritmi.adt.stack;
import it.algoritmi.adt.Stack;
import it.algoritmi.adt.list.SinglyLinkedList;
public class LinkedStack<E> implements Stack<E> {
private SinglyLinkedList<E> list = new SinglyLinkedList<>();
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void push(E element) {
list.addFirst(element);
}
@Override
public E top() {
return list.first();
}
@Override
public E pop() {
return list.removeFirst();
}
}

View File

@@ -0,0 +1,56 @@
package it.algoritmi.test;
import it.algoritmi.adt.Deque;
import it.algoritmi.adt.Queue;
import it.algoritmi.adt.Stack;
import it.algoritmi.adt.dequeue.ArrayDeque;
import it.algoritmi.adt.queue.LinkedQueue;
import it.algoritmi.adt.stack.ArrayStack;
public class ADTs {
public static <E> void transfer(Stack<E> s, Stack<E> t) {
if(!s.isEmpty()) {
for(int i = 0, len = s.size(); i < len; ++i)
t.push(s.pop());
}
}
public static <E> void removeAll(Stack<E> s) {
if(s.isEmpty()) {
return;
}
s.pop();
removeAll(s);
}
public static <E> void shuffle(Deque<E> d) {
Queue<E> q = new LinkedQueue<>();
// TODO
}
@SafeVarargs
private static <E> Stack<E> buildStack(E... elements) {
Stack<E> result = new ArrayStack<>();
for(E elem : elements)
result.push(elem);
return result;
}
@SafeVarargs
private static <E> Deque<E> buildDequeue(E... elements) {
Deque<E> result = new ArrayDeque<>();
for(E elem : elements)
result.addLast(elem);
return result;
}
public static void main(String[] args) {
Stack<Integer> s1 = buildStack(1, 2, 3, 4, 5);
Stack<Integer> s2 = buildStack(6, 7, 8, 9, 0);
transfer(s1, s2);
removeAll(s2);
Deque<Integer> dk = buildDequeue(1, 2, 3, 4, 5, 6, 7, 8);
}
}

View File

@@ -0,0 +1,31 @@
package it.algoritmi.test;
import it.algoritmi.adt.Stack;
import it.algoritmi.adt.stack.LinkedStack;
public class ArithmeticMatcher {
public static boolean isMatched(String expression) {
final String opening = "({[";
final String closing = ")}]";
Stack<Character> buffer = new LinkedStack<>();
for(char c : expression.toCharArray()) {
if(opening.indexOf(c) != -1) {
buffer.push(c);
} else if(closing.indexOf(c) != -1) {
if(buffer.isEmpty()) {
return false;
}
if(closing.indexOf(c) != opening.indexOf(buffer.pop())) {
return false;
}
}
}
return buffer.isEmpty();
}
public static void main(String[] args) {
String exp = "(10 + 4) * 89";
System.out.println(isMatched(exp));
}
}

View File

@@ -0,0 +1,47 @@
package it.algoritmi.test;
public class CaesarCipher {
protected char[] encoder = new char[26];
protected char[] decoder = new char[26];
public CaesarCipher(int rotation) {
for (int k = 0; k < 26; ++k) {
encoder[k] = (char) ('A' + (k + rotation) % 26);
decoder[k] = (char) ('A' + (k - rotation + 26) % 26);
}
}
/** Restituisce il messaggio cifrato. */
public String encrypt(String message) {
return trasform(message, encoder);
}
/** Restituisce il messaggio decifrato. */
public String decrypt(String secret) {
return trasform(secret, decoder);
}
/** Restituisce la trasformazione della stringa ricevuta secondo il codice dato. */
private String trasform(String original, char[] code) {
char[] msg = original.toCharArray();
for (int k = 0; k < msg.length; ++k) {
if(Character.isUpperCase(msg[k])) {
int j = msg[k] - 'A';
msg[k] = code[j];
}
}
return new String(msg);
}
public static void main(String[] args) {
CaesarCipher cipher = new CaesarCipher(3);
System.out.println("Encryption code = " + new String(cipher.encoder));
System.out.println("Decryption code = " + new String(cipher.decoder));
String message = "THE EAGLE IS IN PLAY; MEET AT JOE'S.";
String coded = cipher.encrypt(message);
System.out.println("Secret: " + coded);
String answer = cipher.decrypt(coded);
System.out.println("Message: " + answer);
}
}

View File

@@ -0,0 +1,83 @@
package it.algoritmi.test;
public class CreditCard {
private String customer;
private String bank;
private String account;
private int limit;
protected double balance;
public CreditCard(String customer, String bank, String account, int limit) {
this(customer, bank, account, limit, 0.0);
}
public CreditCard(String customer, String bank, String account, int limit, double balance) {
this.customer = customer;
this.bank = bank;
this.account = account;
this.limit = limit;
this.balance = balance;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public String getBank() {
return bank;
}
public void setBank(String bank) {
this.bank = bank;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public boolean charge(double price) {
if(price + balance > limit) {
return false;
}
balance += price;
return true;
}
public void makePayment(double amount) {
balance -= amount;
}
public static void printSummary(CreditCard card) {
System.out.println("Customer = " + card.customer);
System.out.println("Bank = " + card.bank);
System.out.println("Account = " + card.account);
System.out.println("Balance = " + card.balance);
System.out.println("Limit = " + card.limit);
}
}

View File

@@ -0,0 +1,36 @@
package it.algoritmi.test;
import it.algoritmi.adt.Stack;
import it.algoritmi.adt.stack.LinkedStack;
public class HTMLMatcher {
public static boolean isHTMLMatched(String html) {
Stack<String> buffer = new LinkedStack<>();
int j = html.indexOf('<');
while(j != -1) {
int k = html.indexOf('>', j+1);
if(k == -1) {
return false;
}
String tag = html.substring(j+1, k);
if(!tag.startsWith("/")) {
buffer.push(tag);
} else {
if(buffer.isEmpty()) {
return false;
}
if(!tag.substring(1).equals(buffer.pop())) {
return false;
}
}
j = html.indexOf('<', k+1);
}
return buffer.isEmpty();
}
public static void main(String[] args) {
}
}

View File

@@ -0,0 +1,40 @@
package it.algoritmi.test;
import it.algoritmi.adt.CircularQueue;
import it.algoritmi.adt.queue.LinkedCircularQueue;
public class Josephus {
/** Determina il vincitore del problema di Josephus usando una coda circolare. */
public static <E> E josephus(CircularQueue<E> queue, int k) {
if(queue.isEmpty()) {
return null;
}
while(queue.size() > 1) {
for (int i = 0; i < k-1; ++i) {
queue.rotate();
}
E e = queue.dequeue();
System.out.println(" " + e + " is out");
}
return queue.dequeue();
}
/** Costruisce una coda circolare a partire da un array di oggetti. */
public static <E> CircularQueue<E> buildQueue(E a[]) {
CircularQueue<E> queue = new LinkedCircularQueue<>();
for(int i = 0; i < a.length; ++i) {
queue.enqueue(a[i]);
}
return queue;
}
public static void main(String[] args) {
String[] a1 = {"Alice", "Bob", "Cindy", "Doug", "Ed", "Fred"};
String[] a2 = {"Gene", "Hope", "Irene", "Jack", "Kim", "Lance"};
String[] a3 = {"Mike", "Roberto"};
System.out.println("First winner is " + josephus(buildQueue(a1), 3));
System.out.println("Second winner is " + josephus(buildQueue(a2), 10));
System.out.println("Third winner is " + josephus(buildQueue(a3), 7));
}
}

View File

@@ -0,0 +1,28 @@
package it.algoritmi.test;
public class PredatoryCreditCard extends CreditCard {
private double rate;
public PredatoryCreditCard(String customer, String bank, String account,
int limit, double initialBalance, double rate) {
super(customer, bank, account, limit, initialBalance);
this.rate = rate;
}
public void processMoth() {
if(balance > 0) {
double monthlyFactor = Math.pow(1 + rate, 1. / 12);
balance *= monthlyFactor;
}
}
@Override
public boolean charge(double price) {
boolean isSuccess = super.charge(price);
if(!isSuccess) {
balance += 5;
}
return isSuccess;
}
}