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] nn-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) nn-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