Liste concatenate
Collezione ordinata di nodi
tail
head
next
element
next
element
Anna
next
element
Carlo
element
Paolo
ciascun nodo contiene due riferimenti:
- un riferimento "element" a un elemento
- un riferimento "next" ad un altro nodo
Strutture Dati
next
Simona
Ø
Liste concatenate
Lista concatenata
Ø
. . .
array
0 1
2
somiglianze:
ordinamento lineare
differenze:
la lista concatenata non ha bisogno di una taglia fissata a priori
come accade per l'array (può usare uno spazio propozionale al
numero dei suoi elementi)
Strutture Dati
N-1
La classe Nodo
Implementazione Java
public class Node<E> {
private E element;
private Node<E> next;
public Node(E e, Node<E> n){
element = e;
next = n;
}
public Node(){
this(null,null);
}
public E getElement(){
return element;
}
public Node<E> getNext(){
return next;
}
public void setElement(E newElem) {
element = newElem;
}
public void setNext(Node<E> newNext){
next = newNext;
}
}
Strutture Dati
next
element
Liste concatenate
Implementazione della pila con liste concatenate
l’elemento in cima alla pila è memorizzato nel primo nodo della
lista
head (cima della pila)
Ø
y
Strutture Dati
a
x
v
Liste concatenate
Implementazione della pila con liste concatenate
l’elemento in cima alla pila è memorizzato nel primo nodo della
lista
head (cima della pila)
Ø
y
a
x
v
inserimento di un nuovo elemento e nella pila (push(e))
Strutture Dati
Liste concatenate
Implementazione della pila con liste concatenate
l’elemento in cima alla pila è memorizzato nel primo nodo della
lista
head (cima della pila)
Ø
y
a
x
v
inserimento di un nuovo elemento e nella pila (push(e))
- creiamo un nuovo nodo
Strutture Dati
Liste concatenate
Implementazione della pila con liste concatenate
l’elemento in cima alla pila è memorizzato nel primo nodo della
lista
head (cima della pila)
Ø
e
y
a
x
v
inserimento di un nuovo elemento e nella pila (push(e))
- creiamo un nuovo nodo
- definiamo il riferimento all'elemento e
Strutture Dati
Liste concatenate
Implementazione della pila con liste concatenate
l’elemento in cima alla pila è memorizzato nel primo nodo della
lista
head (cima della pila)
Ø
e
y
a
x
v
inserimento di un nuovo elemento e nella pila (push(e))
- creiamo un nuovo nodo
- definiamo il riferimento all'elemento e
- definiamo il riferimento al nodo successivo
Strutture Dati
Liste concatenate
Implementazione della pila con liste concatenate
l’elemento in cima alla pila è memorizzato nel primo nodo della
lista
head (cima della pila)
Ø
e
y
a
x
v
inserimento di un nuovo elemento e nella pila (push(e))
- creiamo un nuovo nodo
- definiamo il riferimento all'elemento e
- definiamo il riferimento al nodo successivo
- aggiorniamo il riferimento al nodo cima della pila
Strutture Dati
Liste concatenate
Implementazione della pila con liste concatenate
package stack;
import linkedList.Node;//linkedList e` il pacchetto dove abbiamo
inserito la classe Node<E>
public class NodeStack<E> implements Stack<E>{
protected Node<E> top;
protected int size;
public NodeStack(){
top = null;
size = 0;
}
public int size() {
return size;
}
public boolean isEmpty() {
return (size == 0);
}
...
}
Strutture Dati
Liste concatenate
Implementazione della pila con liste concatenate
public class NodeStack<E> implements Stack<E>{
...
public E top() throws EmptyStackException {
if (isEmpty()) throw new EmptyStackException("Lo stack e` vuoto.");
return top.getElement();
}
public void push(E element) {
Node<E> v = new Node<E>(element,top);
top = v;
size++;
}
public E pop() throws EmptyStackException {
if (isEmpty()) throw new EmptyStackException("Lo stack e` vuoto.");
E temp = top.getElement();
top = top.getNext();
size--;
return temp;
}
...
}
Strutture Dati
Liste concatenate
Implementazione della coda con liste concatenate
head (front della coda)
tail (rear della coda)
Ø
e
y
a
x
v
il front della coda è memorizzato nel primo nodo (head) della lista
il rear della coda è memorizzato nell’ultimo nodo (tail) della lista
Strutture Dati
Liste concatenate
Implementazione della pila e della coda
Vantaggi:
- non si deve specificare a priori un limite superiore alla taglia della pila
o della coda (una pila o una coda di n elementi richiederà sempre uno
spazio di dimensione O(n))
- tutte le operazioni richiedono tempo O(1)
Svantaggi:
- l'implementazione è leggermente meno semplice di quella con array
- lo spazio di memoria richiesto da ciascun elemento è un po' maggiore
rispetto alla soluzione con array
Strutture Dati
La struttura dati Coda Doppia
(Deque)
E` un'estensione della struttura dati Coda
- cancellazioni e inserimenti sono possibili da entrambe le
estremità (front e rear)
in
in
out
Strutture Dati
out
Il tipo astratto di dati deque
Tipo di dati e operazioni
Dati:
oggetti arbitrari
Operazioni:
- void addFirst(E e): inserisce un nuovo elemento e all'inizio di D
- void addLast(E e): inserisce un nuovo elemento e alla fine di D
- EremoveFirst(): restituisce e rimuove il primo elemento di D
- E removeLast():
restituisce e rimuove l'ultimo elemento di D
- E getFirst(): restituisce il primo elemento di D
- E getLast(): restituisce l'ultimo elemento di D
- Integer size(): restituisce il numero di elementi di D
- Boolean isEmpty(): è vero se D è vuota, falso altrimenti
Strutture Dati
Il tipo astratto di dati deque
Le eccezioni
Si verifica una EmptyDequeException
quando si invoca uno dei seguenti
metodi su una deque vuota.
- E removeFirst()
- E removeLast()
- E getFirst()
- E getLast()
Strutture Dati
Implementazione deque
L'interfaccia
public interface Deque<E> {
public int size();
public boolean isEmpty();
public E getFirst() throws EmptyDequeException;
public E getLast() throws EmptyDequeException;
public void addFirst (E element);
public void addLast (E element);
public E removeFirst() throws EmptyDequeException;
public E removeLast() throws EmptyDequeException;
}
Strutture Dati
Implementazione deque
Soluzione con liste concatenate
head
tail
Ø
Strutture Dati
Implementazione deque
Soluzione con liste concatenate
head
tail
Ø
come facciamo una removeLast()?
Strutture Dati
Implementazione deque
Soluzione con liste concatenate
head
tail
Ø
come facciamo una removeLast()?
Strutture Dati
Implementazione deque
Soluzione con liste concatenate
head
tail
Ø
come facciamo una removeLast()?
Strutture Dati
Implementazione deque
Soluzione con liste concatenate
head
tail
Ø
come facciamo una removeLast()?
Strutture Dati
Implementazione deque
Soluzione con liste concatenate
head
tail
Ø
come facciamo una removeLast()?
Strutture Dati
Implementazione deque
Soluzione con liste concatenate
head
tail
Ø
questa soluzione è inefficiente perché
removeLast() richiederebbe tempo O(n), dove n è
il numero di elementi nella deque
tempo necessario per aggiornare il riferimento next dell'ultimo
nodo e il riferimento al nodo tail
Strutture Dati
Implementazione deque
Soluzione con liste concatenate
header
trailer
prev
next
Ciascun nodo contiene un riferimento (next) al nodo successivo e un riferimento
(prev) al nodo precedente;
Per semplificare la programmazione si usano due nodi speciali detti nodi
sentinella:
nodo header
- next contiene un riferimento al primo nodo della deque
- prev contiene null
nodo trailer
- prev contiene un riferimento all'ultimo nodo della deque
- next contiene null
Strutture Dati
Implementazione deque
Soluzione con liste concatenate
Inserimento in testa di un nuovo elemento
header
trailer
Sempronio
Tizio
Strutture Dati
Caio
Implementazione deque
Soluzione con liste concatenate
Inserimento in testa di un nuovo elemento
header
trailer
Sempronio
Tizio
Strutture Dati
Caio
Implementazione deque
Soluzione con liste concatenate
Inserimento in testa di un nuovo elemento
header
trailer
Sempronio
Tizio
Strutture Dati
Caio
Liste doppiamente concatenate
La classe DLNode
public class DLNode<E> {
private E element;
private DLNode<E> next, prev;
next
prev
element
public DLNode() { this(null, null, null); }
public DLNode(E e, DLNode<E> p, DLNode<E> n) {
element = e;
next = n;
prev = p;
}
public
public
public
public
public
public
}
Strutture Dati
void setElement(E newElem) { element = newElem; }
void setNext(DLNode<E> newNext) { next = newNext; }
void setPrev(DLNode<E> newPrev) { prev = newPrev; }
E getElement() { return element; }
DLNode<E> getNext() { return next; }
DLNode<E> getPrev() { return prev; }
La struttura dati array list
E` un contenitore di elementi organizzati secondo un
ordinamento lineare:
primo elemento, secondo elemento, ...
Strutture Dati
La struttura dati array list
E` un contenitore di elementi organizzati secondo un
ordinamento lineare:
primo elemento, secondo elemento, ...
cancellazioni e inserimenti sono possibili in posti
arbitrari
Strutture Dati
La struttura dati array list
E` un contenitore di elementi organizzati secondo un
ordinamento lineare:
primo elemento, secondo elemento, ...
inserimento di un nuovo
oggetto
cancellazioni e inserimenti sono possibili in posti
arbitrari
Strutture Dati
La struttura dati array list
E` un contenitore di elementi organizzati secondo un
ordinamento lineare:
primo elemento, secondo elemento, ...
cancellazione di un oggetto
cancellazioni e inserimenti sono possibili in posti
arbitrari
Strutture Dati
La struttura dati array list
E` un contenitore di elementi organizzati secondo un
ordinamento lineare:
primo elemento, secondo elemento, ...
cancellazione di un oggetto
cancellazioni e inserimenti sono possibili in posti
arbitrari
Strutture Dati
La struttura dati array list
L'accesso agli elementi avviene per mezzo del loro indice
Dato un array list S di n elementi,
possiamo riferirci univocamente a ciascun
elemento di S attraverso il suo indice:
l'ndice di un elemento e in S è il numero di
elementi che precedono e in S
elemento di indice 0
L'indice di un elemento e
rappresenta la posizione di e
all'interno dell' ordinamento lineare
della struttura:
S
l'elemento i-esimo ha indice i - 1
elemento di indice 3
Strutture Dati
La struttura dati array list
Naturalmente:
l'indice di un elemento e si può modificare
in seguito a inserimenti e cancellazioni
elemento di indice 0
Prima
S
elemento di indice 3
Strutture Dati
La struttura dati array list
Naturalmente:
l'indice di un elemento e si può modificare
in seguito a inserimenti e cancellazioni
Inserimento
Strutture Dati
S
La struttura dati array list
Naturalmente:
l'indice di un elemento e si può modificare
in seguito a inserimenti e cancellazioni
elemento di indice 1
Dopo
S
elemento di indice 4
Strutture Dati
Il tipo astratto di dati array list
Tipo di dati e operazioni
Dati:
oggetti arbitrari
Operazioni:
- get(i): restituisce l'elemento di indice i
- set(i, e): restituisce e rimpiazza l'elemento di indice i con l’elemento e
- add(i, e): inserisce un nuovo elemento e di indice i
- remove(i): restituisce e rimuove l'elemento di indice i
- size()
- isEmpty()
Strutture Dati
Il tipo astratto di dati array list
Le eccezioni
Dato un array list S di n elementi, si verifica una
eccezione nei seguenti casi:
get(i)
con i < 0 oppure i > n - 1
set(i, e) con i < 0 oppure i > n - 1
remove(i)
con i < 0 oppure i > n – 1
add(i, e)
con i < 0 oppure i > n
...
S
0
Strutture Dati
1
2
...
i
n-1
Implementazione array list
L'interfaccia
public interface IndexList<E> {
public int size();
public boolean isEmpty();
public void add(int i, E e)
throws IndexOutOfBoundsException;
public E get(int i)
throws IndexOutOfBoundsException;
public E remove(int i)
throws IndexOutOfBoundsException;
public E set(int i, E e)
throws IndexOutOfBoundsException;
}
Strutture Dati
Implementazione array list
Una semplice soluzione basata su array
L'array list viene implementato con un array A di N elementi e una variabile n < N
che indica il numero di elementi nell'array list
A[i] mantiene un riferimento all'elemento di indice i
...
0
Strutture Dati
1
2
...
i
n-1
N-1
Implementazione array list
Una semplice soluzione basata su array
L'array list viene implementato con un array A di N elementi e una variabile n < N
che indica il numero di elementi nell'array list
A[i] mantiene un riferimento all'elemento di indice i
...
0
1
2
...
i
n-1
Algorithm get(i):
if i < 0 or i > n-1 then
throw BoundaryViolationException
return A[i]
Strutture Dati
N-1
Implementazione array list
Una semplice soluzione basata su array
L'array list viene implementato con un array A di N elementi e una variabile n < N
che indica il numero di elementi nell'array list
A[i] mantiene un riferimento all'elemento di indice i
...
0
1
2
e
i
...
n-1
Algorithm remove(i):
if i < 0 or i > n-1 then
throw BoundaryViolationException
e  A[i]
for j = i, i+1, ..., n - 2 do
A[j]  A[j+1]
nn-1
return e
Strutture Dati
N-1
Implementazione array list
Una semplice soluzione basata su array
L'array list viene implementato con un array A di N elementi e una variabile n < N
che indica il numero di elementi nell'array list
A[i] mantiene un riferimento all'elemento di indice i
...
0
1
2
...
i
n-1
N-1
Algorithm remove(i):
if i < 0 or i > n-1 then
throw BoundaryViolationException
e  A[i]
for j = i, i+1, ..., n - 2 do
A[j]  A[j+1]
tempo di esecuzione: Θ(n)
nn-1
nel caso pessimo (quando i=0)
return e
Strutture Dati
Implementazione array list
Una semplice soluzione basata su array
L'array list viene implementato con un array A di N elementi e una variabile n < N
che indica il numero di elementi nell'array list
A[i] mantiene un riferimento all'elemento di indice i
...
0
1
2
...
i
n-1
N-1
Algorithm add(i, e):
if i < 0 or i > n then
throw BoundaryViolationException
for j = n - 1, n - 2, ..., i do
A[j+1]  A[j]
// fa spazio al nuovo elemento
A[i]  e
n  n+1
Strutture Dati
Implementazione array list
Una semplice soluzione basata su array
L'array list viene implementato con un array A di N elementi e una variabile n < N
che indica il numero di elementi nell'array list
A[i] mantiene un riferimento all'elemento di indice i
...
0
1
2
e
i
...
n-1
N-1
Algorithm add(i, e):
if i < 0 or i > n then
throw BoundaryViolationException
for j = n - 1, n - 2, ..., i do
A[j+1]  A[j]
// fa spazio al nuovo elemento
A[i]  e
tempo di esecuzione: Θ(n)
n  n+1
nel caso pessimo (quando i=0)
Strutture Dati