Fondamenti di Informatica Prof. E. Clementini. Dispensa didattica A.A

Dimensione: px
Iniziare la visualizzazioe della pagina:

Download "Fondamenti di Informatica Prof. E. Clementini. Dispensa didattica A.A. 2008-09"

Transcript

1 Argomenti: Fondamenti di Informatica Prof. E. Clementini Dispensa didattica A.A Efficienza dei programmi. La funzione t(n). Modello di costo. Calcolo della t(n) per programmi iterativi. Caso migliore, caso peggiore, e caso medio. Complessità computazionale. Notazione asintotica O ( g( n)), ( g ( n)), ( g ( n)). Delimitazioni alla complessità di un problema. Calcolo della t(n) per programmi ricorsivi. Soluzione dell equazione di ricorrenza per il fattoriale e per i numeri di Fibonacci. 2. Algoritmi di ricerca e ordinamento. Ricerca sequenziale. Ricerca binaria. Inserimento e cancellazione in un array ordinato. SelectionSort. InsertionSort. Bubblesort. Mergesort. Quicksort: analisi della complessità nel caso migliore e nel caso peggiore. 3. Tipi di dato astratti. Liste: definizioni, rappresentazione con array, rappresentazione con lista collegata, rappresentazione con lista collegata bidirezionale, operazioni primitive sulle liste. Pile: definizioni, rappresentazione con array, rappresentazione con lista collegata, operazioni primitive sulle pile. Code: definizioni, prima rappresentazione con array, seconda rappresentazione con array (gestione circolare), rappresentazione con lista collegata, operazioni primitive sulle code. Alberi: definizioni, alberi n-ari, alberi binari, algoritmi di visita in profondità e in larghezza. Alberi binari: rappresentazione con puntatori, codifica delle operazioni primitive. Calcolo della complessità in programmi che fanno uso di tipi astratti. Università degli Studi dell Aquila 1

2 1. Efficienza dei programmi Calcolo della t(n) Calcolo della t(n) per un ciclo for Numeriamo le istruzioni elementari rispettando lo stesso ordine di esecuzione del diagramma di flusso. Quindi nell esempio seguente l incremento della variabile è numerato dopo le istruzioni interne al ciclo: 1 2 for(i=0;i<n;i++) cin>>x; 3 somma=somma+x; 5 4 Tabella costo/frequenza: # istr. costo freq n n 4 1 n 5 1 n t(n)=4n+2 Calcolo della t(n) per un doppio ciclo. Due casi: a) il numero di esecuzioni del ciclo interno non dipende dall iterazione del ciclo esterno; b) il numero di esecuzioni del ciclo interno dipende dall iterazione del ciclo esterno. Caso a) somma dei valori di una tavola pitagorica: 1 2 for (i=1;i<=n;i++) for (j=1;j<=n;j++) somma=somma+ i*j; 5 7 Università degli Studi dell Aquila 2

3 # istr. costo freq n n 4 1 n(n+1) n n 7 1 n t(n)=3 n 2 +4n+2 Caso b) Piramide di numeri: 1 2 for (i=1;i<=n;i++) 5 3 for (j=1;j<=i;j++) cout<<j; Il costo del ciclo interno può essere calcolato determinando la sua frequenza per ogni valore del contatore esterno i: per i=1: 1 j 1, freq. 1 per i=2: 1 j 2, freq. 2 per i=n: 1 j n, freq. n Il totale delle frequenze parziali è Tabella: n k 1 k = n(n 2 1). # istr. costo freq n n 4 1 n(n+1)/2+n 5 1 n(n+1)/2 6 1 n(n+1)/2 7 1 n 3 11 t(n)= n 2 n Università degli Studi dell Aquila 3

4 Complessità computazionale Notazione asintotica Limite asintotico superiore O ( g( n)) O ( g( n)) = f ( n) c, n,0 f ( n) cg( n), n 0 n0 Limite asintotico inferiore ( g ( n)) ( g ( n)) = f ( n) c, n,0 cg( n) f ( n), n 0 n0 Limite asintotico stretto ( g ( n)) ( g ( n)) = f ( n) c, c, n,0 c g( n) f ( n) c g( n), n n0 Proprietà della notazione asintotica: - fattore costante: k, f (n), k f ( n) ( f ( n)) - transitività: f ( n) ( g( n)), g ( n) ( h( n)) f ( n) ( h( n)) - somma: f ( n) g( n) = (max f ( n), g( n)) - prodotto: f n) ( g ( )), f n) ( g ( )) f n) f ( ) = g ( n) g ( )) 1( 1 n 2 ( 2 n 1( 2 n ( 1 2 n Istruzione dominante L istruzione dominante è l istruzione che viene ripetuta con frequenza maggiore in un programma. Se riusciamo a calcolare la frequenza e quindi la complessità dell istruzione dominante, conosciamo la complessità di tutto l algoritmo. Delimitazione superiore di un problema Un problema ha una delimitazione superiore O ( f ( n)) se esiste almeno un algoritmo che lo risolve con complessità O ( f ( n)). Delimitazione inferiore di un problema Un problema ha una delimitazione inferiore ( f ( n)) se ogni algoritmo che lo risolve ha complessità almeno ( f ( n)). Soluzione ottima di un problema Dato un problema con una delimitazione inferiore ( f ( n)), una soluzione ottima è un algoritmo che risolve il problema con complessità ( f ( n)). Università degli Studi dell Aquila 4

5 Calcolo t(n) di una funzione ricorsiva Funzione fattoriale int fatt (int n) 1 2 if (n==0) return 1; return n*fatt(n-1); 3 # istr. costo freq. (n>0) freq. (n=0) t(n-1) 1 0 Equazione di ricorrenza: t(n)=t(n-1)+1 per n>0 e t(0)=2 Risolviamo per sostituzione: t(n-1)=t(n-2)+1 t(n)=t(n-2)+2 t(n-2)=t(n-3)+1 t(n)=t(n-3)+3 t(n)=t(0) +n t(n)=n+2 Numeri di Fibonacci Un termine della serie di Fibonacci è definito matematicamente come: f ; 0 1 f ; 1 1 f f f, n 1. n n 1 n 2 Università degli Studi dell Aquila 5

6 Soluzione ricorsiva: int fib(int n) 1 if (n==0 n==1) return 1; return fib(n-1)+fib(n-2); 2 3 # istr. costo freq. (n>1) freq. (n=0 or n=1) t(n-1)+t(n-2) 1 0 Equazione di ricorrenza: t(n)=t(n-1)+t(n-2)+1 per n>1 e t(n)=2 per n=0 or n=1 per sostituzione: t(n-1)=t(n-2)+t(n-3)+1 t(n)= t(n-2)+t(n-3)+1 +t(n-2) +1 = 2 t(n-2) +t(n-3) +2 t(n-2)=t(n-3)+t(n-4)+1 t(n)=2 t(n-3) +2 t(n-4) +2 +t(n-3) +2 = 3 t(n-3)+2t(n-4)+4 t(n-3)=t(n-4)+t(n-5)+1 t(n)=3t(n-4)+3t(n-5)+3+2t(n-4)+4 = 5t(n-4)+3t(n-5) +7 t(n-4)=t(n-5)+t(n-6)+1 t(n)=5t(n-5)+5t(n-6)+5+3t(n-5) +7 = 8t(n-5)+5t(n-6)+12 = f 5 t(n-5)+ f 4 t(n-6)+ f 6-1 t(n)= f 6 t(n-6) + f 5 t(n-7) + f t(n)= f n 1t(1) + f n 2 t(0) + f n -1 = 2 f n 1+2 f n 2 t(n)= 3 f n 1 + n f -1 = 2( f n 1 + f n 2 )+ f n -1 = 3 f n -1. La funzione t(n) cresce come i numeri di Fibonacci, quindi è esponenziale. Infatti, si trova empiricamente che una delimitazione per i numeri di Fibonacci è la seguente: f n n L algoritmo iterativo per calcolare i numeri di Fibonacci ha invece costo lineare. Università degli Studi dell Aquila 6

7 2. Algoritmi di ricerca e ordinamento Ricerca sequenziale L ordinamento dei valori contenuti in un array, in senso crescente o decrescente, è utile per ritrovare più facilmente i valori in svariate applicazioni. Sono i tempi di calcolo ad essere inferiori se dobbiamo ritrovare un valore all interno di un array ordinato piuttosto che all interno di un array non ordinato. Il problema della ricerca può essere formulato come segue: Esiste il valore k all interno dell array v?. Per rispondere, in un array non ordinato possiamo solo adottare un cosiddetto algoritmo di ricerca sequenziale, costituito da un ciclo che scandisce tutto l array. Osserviamo il seguente frammento di codice: i=0; 1 trovato=false; 2 while(i<n &&!trovato) if (v[i]==k) 4 trovato=true; i++; 6 Come si può vedere, il tempo di esecuzione è più o meno sfavorevole a seconda della posizione che l elemento cercato assume all interno dell array. Se l elemento non dovesse essere presente, abbiamo dovuto esaminare tutto l array per giungere a questa conclusione. Il caso peggiore corrisponde a trovare l elemento in ultima posizione (oppure in modo quasi equivalente a non trovarlo affatto), mentre il caso migliore corrisponde a trovare l elemento in prima posizione. Il caso medio può essere calcolato con considerazioni statistiche: se ipotizziamo che il numero di elementi dell array n sia uguale al numero di valori possibili, è lecito ipotizzare che mediamente il valore k si trova a metà array. # istr. costo freq. (c.p.) freq. (c.migliore) freq. (c.medio) n+1 2 n/ n 1 n/ n 1 n/2 Caso peggiore t(n)=3n+4 Caso migliore t(n)=7 Caso medio t(n)=3n/ Università degli Studi dell Aquila 7

8 Applicando lo stesso algoritmo ad un array ordinato in senso crescente, possiamo migliorare il codice aggiungendo un ulteriore condizione di uscita quando il valore contenuto nell array supera il valore da cercare: i=0; trovato=false; while(i<n &&!trovato && v[i]<=k) if (v[i]==k) trovato=true; i++; In questa versione il caso peggiore si verifica quando l elemento cercato è in ultima posizione oppure quando è più grande di tutti i valori dell array. Il caso migliore si verifica quando l elemento cercato è più piccolo di tutti i valori dell array (in questo caso non si entra per niente nel ciclo): # istr. costo freq. (c.p.) freq. (c.m.) n n n 0 Caso peggiore t(n)=3n+4 Caso migliore t(n)=3 Ricerca binaria In un array ordinato, è possibile applicare un algoritmo molto più efficiente, la cosiddetta ricerca binaria. In questo algoritmo, si accede all elemento di mezzo dell array v[med] e si controlla se esso è maggiore o minore del valore cercato k: se è maggiore, il valore k dovrà trovarsi nella prima metà dell array, altrimenti nella seconda metà. Pertanto dopo un solo controllo l algoritmo ha escluso metà degli elementi. Ripetendo il procedimento sulla metà interessata, si potrà escludere un altro quarto di array, e così via. Si intuisce che dopo pochi controlli, si arriva subito alla conclusione. Consideriamo il seguente esempio: v min med max Università degli Studi dell Aquila 8

9 Il valore di med in questo caso è uguale a 5. Supponiamo che k sia uguale a 10. Poiché v[5] è maggiore di 10, si assegna a max il valore di med-1. Nell iterazione successiva, in questo modo si considera la prima metà dell array per cercare il valore k. La codifica in C++ è la seguente: max=n-1; 1 min=0; 2 trovato=false; 3 4 while(max>=min &&!trovato) med=(max+min)/2; 5 if (v[med]==k) 6 trovato=true; 7 8 if (v[med]>k) max=med-1; 9 min=med+1; Il caso peggiore corrisponde all elemento non presente nell array e il caso migliore all elemento trovato durante la prima iterazione: # istr. costo freq. (c.p.) freq. (c.m.) log 2 n log 2 n log 2 n log 2 n log 2 n Caso peggiore t(n)=5 Caso migliore t(n)=8 log n +9 2 Il costo logaritmico è dovuto al numero di divisioni necessarie partendo da un vettore di n elementi per arrivare a una parte di vettore costituita da un solo elemento. Università degli Studi dell Aquila 9

10 Inserimento e cancellazione in un array ordinato Quando si ha a disposizione un array ordinato, è conveniente mantenerlo ordinato anche in seguito all aggiunta o alla cancellazione di nuovi valori. Partiamo ad esempio dall array seguente e supponiamo di voler inserire un nuovo valore x=20: per mantenere l ordinamento, dobbiamo memorizzare x in posizione p=4 e spostare tutti gli altri valori in avanti di una posizione: v Il frammento di codice seguente esegue l inserimento di un valore x in un array ordinato in posizione p: for (int i=n-1;i>=p;i--) v[i+1]=v[i]; 3 v[p]=x; 5 n++; Il risultato sarà il seguente: 4 v Ovviamente per poter spostare i valori in avanti, l array deve essere stato dichiarato con un numero di elementi maggiore di n. Il caso peggiore corrisponde all inserimento per p=0, quando bisognerà spostare tutti gli elementi presenti in avanti, e il caso migliore all inserimento per p=n, quando sarà sufficiente memorizzare il valore nella prima posizione libera del vettore senza dover spostare elementi: # istr. costo freq. (c.p.) freq. (c.m.) n n n Caso peggiore t(n)=3n+4 Caso migliore t(n)=4 Università degli Studi dell Aquila 10

11 In maniera equivalente, per la cancellazione di un valore in posizione p, si dovranno spostare all indietro tutti i valori successivi alla posizione stessa. Si osservi il frammento di codice: for (int i=p;i<n-1;i++) v[i]=v[i+1]; 3 n--; 4 Il caso peggiore corrisponde alla cancellazione per p=0, quando bisognerà spostare i restanti n-1 elementi del vettore all indietro, e il caso migliore all inserimento per p=n-1, quando sarà sufficiente diminuire di 1 il numero n senza dover spostare elementi: # istr. costo freq. (c.p.) freq. (c.m.) n n n Caso peggiore t(n)=3n Caso migliore t(n)=3 Università degli Studi dell Aquila 11

12 Selectionsort Per poter usare la ricerca binaria, è necessario ordinare i valori di un array nel caso si parta da valori disordinati. Esistono svariati algoritmi di ordinamento, che si differenziano in base alle prestazioni. In questa sezione, vediamo un semplice algoritmo, chiamato ordinamento per selezione, che non è tra i più efficienti. L ordinamento per selezione si basa sul trovare il valore più piccolo dell array e scambiare tale valore con quello in prima posizione. Successivamente, si trova il valore più piccolo tra gli n-1 valori rimasti e si mette in seconda posizione, e così via. Il frammento di codice relativo è il seguente: 1 2 for (i=0;i<n-1;i++) min=i; for (j=i+1;j<n;j++) if (v[j]<v[min]) min=j; temp=v[i]; 9 v[i]=v[min]; 10 v[min]=temp; Il caso peggiore corrisponde ad un array ordinato in senso inverso, mentre il caso migliore ad un array già ordinato. Tuttavia, come si vede nella tabella costi-frequenze, i due casi praticamente coincidono a meno del costo dell istruzione n. 7. Il costo del ciclo interno può essere calcolato determinando la sua frequenza per ogni valore del contatore esterno i: per i=0: 1 j n 1, freq. n-1 per i=1: 2 j n 1, freq. n-2 per i=n-2: n 1 j n 1, freq. 1 Il totale delle frequenze parziali è n 1 k 1 k = n(n 2 1). Università degli Studi dell Aquila 12

13 Tabella: # istr. costo freq. (c.p.) freq. (c.m.) n n 3 1 n-1 n n-1 n n(n-1)/2+n-1 n(n-1)/2+n n(n-1)/2 n(n-1)/2 7 1 n(n-1)/ n(n-1)/2 n(n-1)/2 9 1 n-1 n n-1 n n-1 n n-1 n-1 Caso peggiore t(n)= 2n 2 6n Caso migliore t(n)= n 2 n Università degli Studi dell Aquila 13

14 Insertionsort L algoritmo di ordinamento per inserimento, o insertionsort, si basa sull inserire man mano dei valori all interno di una parte di array già ordinata. Il frammento di codice relativo è il seguente: 1 2 for (i=0;i<n-1;i++) x=v[i+1]; for (j=i;j>=0 && v[j]>x;j--) v[j+1]=v[j]; 6 7 v[j+1]=x; 8 Il caso peggiore corrisponde ad un array ordinato in senso inverso, mentre il caso migliore ad un array già ordinato. Nel caso migliore l algoritmo diventa lineare. Il costo del ciclo interno può essere calcolato determinando la sua frequenza per ogni valore del contatore esterno i: per i=0: 0 j 0, freq. 1 per i=1: 1 j 0, freq. 2 per i=n-2: n 2 j 0, freq. n-1 Il totale delle frequenze parziali è n 1 k 1 k = n(n 2 1). # istr. costo freq. (c.p.) freq. (c.m.) n n 3 1 n-1 n n-1 n n(n-1)/2+n-1 n n(n-1)/ n(n-1)/ n-1 n n-1 n Caso peggiore t(n)= n 2 n Caso migliore t(n)= 6n 4 Università degli Studi dell Aquila 14

15 Bubblesort L algoritmo di ordinamento a bolle, o bubblesort, si basa sull effettuare confronti tra elementi adiacenti, che vanno scambiati se non rispettano l ordinamento. Il procedimento va ripetuto fino all ordinamento completo del vettore. Ad ogni iterazione interna, l algoritmo assicura che l elemento più piccolo della parte ancora da ordinare affiora fino ad accodarsi alla parte già ordinata. Questo schema base può essere migliorato osservando che se un iterazione interna non effettua nessuno scambio di elementi, allora il vettore risulta essere ordinato e quindi si può interrompere il procedimento. Il frammento di codice relativo è il seguente: i=0; do 1 scambio=false; for (j=n-1;j>i;j--) if (v[j]<v[j-1]) 5 temp=v[j]; 6 v[j]=v[j-1]; 7 v[j-1]=temp; scambio=true; 8 9 i=i+1; while(i<n-1 && scambio); Il caso peggiore corrisponde ad un array ordinato in senso inverso, mentre il caso migliore ad un array già ordinato. Nel caso migliore l algoritmo diventa lineare. Il costo del ciclo interno può essere calcolato determinando la sua frequenza per ogni valore del contatore esterno i: per i=0: n 1 j 1, freq. n-1 per i=1: n 1 j 2, freq. n-2 per i=n-2: n 1 j n 1, freq. 1 Il totale delle frequenze parziali è n 1 k 1 k = n(n 2 1). Università degli Studi dell Aquila 15

16 # istr. costo freq. (c.p.) freq. (c.m.) n n n(n-1)/2+n-1 n 5 1 n(n-1)/2 n n(n-1)/ n(n-1)/ n(n-1)/ n(n-1)/ n(n-1)/2 n n n Caso peggiore t(n)= n 2 n Caso migliore t(n)= 3n 3 Tabella comparativa dei tre metodi quadratici di ordinamento: Algoritmo Caso peggiore Caso migliore Selectionsort 2n 2 6n n 2 n Insertionsort n 4 n n Bubblesort n 3 n n Università degli Studi dell Aquila 16

17 Mergesort L algoritmo di ordinamento per fusione (mergesort) segue l approccio divide et impera : si divide il problema in sottoproblemi; si risolvono i sottoproblemi; si combinano i risultati. In particolare, in questo algoritmo si divide il vettore per 2 fino ad ottenere segmenti di lunghezza 1: successivamente si riassemblano segmenti di vettori ordinati in un vettore di lunghezza doppia tramite fusione. Per capire come funziona l algoritmo, è necessario descrivere la fusione. La fusione (o merge) si riferisce al problema di ottenere, dati due vettori ordinati, un unico vettore ordinato che contiene gli elementi di entrambi i vettori di partenza. Il vettore risultante sarà di lunghezza pari alla somma delle due lunghezze dei vettori dati La seguente funzione ottiene la fusione di due parti di vettore comprese tra gli indici q e t, e t+1 e r, rispettivamente. Il vettore dato si chiama v, mentre w è un vettore di appoggio. void merge (vettore v, int q, int t, int r) vettore w; int i=q; int j=t+1; int k=q; 1 2 while (i<=t && j<=r) if (v[i]<=v[j]) w[k]=v[i]; i=i+1; Università degli Studi dell Aquila 17

18 w[k]=v[j]; j=j+1; 9 k=k+1; 10 8 if (i<=t) 11 do w[k]=v[i]; k=k+1; 13 i=i+1; 14 while (i<=t); 15 do w[k]=v[j]; k=k+1; 17 j=j+1; 18 while (j<=r); for (k=q; k<=r; k=k+1) v[k]=w[k]; 22 Pongo n=r-q+1 n1=t-q+1 n2=r-t n1+n2=n # istr. costo freq. (c.p.) freq. (c.m.) n n n-1 n1 6 1 n1 n1 7 1 n1 n1 8 1 n n2-1 0 Università degli Studi dell Aquila 18

19 10 1 n-1 n n n n n n+1 n n n 23 1 n n Nel caso peggiore consideriamo il caso in cui il ciclo while ricopia il massimo di elementi (n- 1 elementi), cioè, per semplificare, il caso in cui si alterna la copia di un elemento dal primo e dal secondo vettore: t(n)=6n+2n1+2n2+6= (ponendo n1=n2=n/2) =8n+6 nel caso migliore, consideriamo il caso in cui il primo ciclo ricopia gli elementi solo del primo vettore e mai del secondo, cioè quando gli elementi del primo vettore vengono tutti prima degli elementi del secondo vettore: t(n)=3n+5n1+4n2+7= (ponendo n1=n2=n/2) =15/2 n +7 Il seguente codice realizza l algoritmo di mergesort: void mergesort (vettore v, int q, int r) int t; if (q<r) 1 t=(q+r)/2; 2 mergesort (v,q,t); 3 mergesort (v,t+1,r); merge (v,q,t,r); chiamata: mergesort (v,0,n-1); Università degli Studi dell Aquila 19

20 n=r-q+1 q<r n>1 # istr. costo freq. (n>1) freq. (n=1) t(n/2) t(n/2) n Equazione di ricorrenza: t(n) =2t(n/2)+8n+8 t(1)=1 Per avere un equazione più generale, poniamo: t(n)=2t(n/2)+cn+d Soluzione: t(n/2)=2t(n/4)+cn/2+d t(n)=4t(n/4)+cn+2d+cn+d=4t(n/4)+2cn+3d t(n/4)=2t(n/8)+cn/4+d t(n)=8t(n/8)+cn+4d+2cn+3d=8t(n/8)+3cn+7d t(n/8)=2t(n/16)+cn/8+d t(n)= 16t(n/16)+cn+8d +3cn+7d= 16t(n/16)+4cn+15d. t(n) = n t( 1) log2 n cn ( n 1) d = = cn log 2 n ( d 1) n d = = 8n log2 n 9n 8 Applichiamo l algoritmo a un vettore con numero di elementi pari a una potenza di 2, per descrivere più facilmente il funzionamento. Consideriamo ad esempio il seguente vettore con 8 elementi: v Le chiamate ricorsive determinate dall algoritmo sono schematizzate come nella figura p seguente. Abbiamo un numero di chiamate della funzione mergesort per n 2 pari a: Università degli Studi dell Aquila 20

21 = = p k 2 = 2 p 1 1 k 0 = 2n-1. Il numero di chiamate della funzione merge è 2 p 1 = n-1 E possibile stimare il tempo di calcolo osservando che abbiamo un tempo di esecuzione lineare per ogni livello della figura dovuto alle attivazioni della funzione merge su n elementi. Inoltre i livelli sono pari a p e quindi in totale abbiamo un tempo nlogn. livello livello livello livello livello 2 merge(v,0,0,1) merge(v,2,2,3) merge(v,4,4,5) merge(v,6,6,7) merge(v,0,1,3) merge(v,4,5,7) livello merge(v,0,3,7) livello Università degli Studi dell Aquila 21

22 Quicksort Anche il quicksort è un algoritmo basato su una strategia divide et impera. La suddivisione dell array da ordinare non avviene nel punto di mezzo come nel mergesort, ma attraverso una operazione di partizione che suddivide l array in due parti tali che nella prima parte ci siano tutti i valori minori o uguali a un valore fissato (detto pivot) e nella seconda parte ci siano tutti i valori maggiori o uguali al pivot. La seguente funzione che realizza la partizione dell array sceglie come elemento pivot il primo elemento dell array. La funzione scandisce l array con due indici da estremi opposti, scambiando di volta in volta le coppie di valori che non rispettano la condizione desiderata. Esempio di vettore v con pivot x[0]=8: Università degli Studi dell Aquila 22

23 int partizione (vettore v, int q, int r) int i,j,x ; 1 2 x=v[q] ; i=q-1 ; j=r+1 ; //x pivot while (i<j) do j=j-1 while (v[j]>x); 7 do i=i+1 while (v[i]<x); if (i<j) scambia (v[i],v[j]); 10 return j; 11 Università degli Studi dell Aquila 23

24 Calcolo della t(n): n=r-q+1 # istr. costo freq. (array freq. freq. (suddivisione ordinato) (suddivisione a a metà, con max metà, con 1 solo scambi) scambio) n/ n n/2 n/2 6 1 n n/2 n/ n/2 n/ n/2 n/ n/ n/ Caso peggiore per il quicksort: array ordinato t(n)=2n+9 Caso migliore per il quicksort: suddivisione sempre a metà - con 1 scambio (scambio solo pivot): t(n)=2n+12 - con max scambi: t(n)=9/2 n + 5 La funzione quicksort: void quicksort (vettore v, int q, int r) int t; if (q<r) 1 t=partizione(v,q,r); quicksort (v,q,t); 3 quicksort (v,t+1,r); 2 4 # istr. costo (c.p.) costo (c.m.) freq. (n>1) freq. (n=1) n+9 2n t(1) t(n/2) t(n-1) t(n/2) 1 0 Università degli Studi dell Aquila 24

25 Caso migliore (suddivisione perfettamente bilanciata, la funzione partizione ogni volta divide il vettore a metà): t(n)=2t(n/2) + 2n + 13 t(1)=1 soluzione come il mergesort: t(n) = cn log 2 n ( d 1) n d = 2n log2 n 14n 13. Caso ottimale: Partizione bilanciata Costo n log n pari al numero dei livelli per il costo lineare della partizione: Caso peggiore (array già ordinato e conseguente suddivisione totalmente sbilanciata; ogni chiamata di partizione suddivide il vettore in una parte di un solo elemento e una parte dei restanti elementi): t(n)= t(n-1) + t(1) + 2n +10 t(1)=1 Poniamo: t(n) = t(n-1) + 2n + 11 = t(n-1) + cn +d soluzione: t(n-1)=t(n-2) + c(n -1) +d t(n)=t(n-2) + c(n -1) +d + cn +d =t(n-2)+ c(n -1) + cn +2d t(n-2)=t(n-3) + c(n-2) +d t(n)= t(n-3) + c(n-2) +d + c(n -1) + cn +2d =t(n-3)+ c(n-2) + c(n -1) + cn +3d t(n-3)=t(n-4) + c(n-3) +d t(n)= t(n-4) + c(n-3) +d + c(n-2) + c(n -1) + cn +3d = t(n-4)+c(n-3)+c(n-2)+c(n -1)+cn +4d... t(n)= t(1) + c 2 + c c(n-3)+c(n-2)+c(n -1)+cn + (n-1) d = Università degli Studi dell Aquila 25

26 = 1 + c = 2 n k 2 n 12n 12 k + d (n-1) = 1 + c n(n 2 1) c 2 c - c +d(n-1) = n d n c d Caso peggiore: Partizione sbilanciata Costo quadratico pari al numero dei livelli per il costo lineare della partizione Università degli Studi dell Aquila 26

27 Tabella comparativa dei metodi nlogn di ordinamento: Algoritmo Caso peggiore Caso migliore t(n) ( g ( n)) t(n) ( g ( n)) Mergesort 8n log2 n 9n 8 ( n logn) 8n log2 n 9n 8 ( n logn) 2 Quicksort n 12n 12 ( n 2 ) 2n log2 n 14n 13 ( n logn) Tabella comparativa dei metodi di ordinamento: Caso peggiore Caso medio Caso migliore Mergesort ( n logn) ( n logn) ( n logn) Quicksort ( n 2 ) ( n logn) ( n logn) Selectionsort ( n 2 ) ( n 2 ) ( n 2 ) Insertionsort ( n 2 ) ( n 2 ) (n) Bubblesort ( n 2 ) ( n 2 ) (n) Algoritmi ottimi: Per il problema dell ordinamento, la delimitazione inferiore della complessità è ( n logn). Pertanto, il solo algoritmo ottimo che abbiamo trattato è il mergesort che ha complessità nel caso peggiore ( n logn). Per il problema della ricerca, la delimitazione inferiore della complessità è (logn). Pertanto la ricerca binaria è un algoritmo ottimo perché risolve il problema in tempo (logn). Le notazioni asintotiche si possono applicare anche allo spazio di memoria utilizzato e non solo al tempo. Occupazione di memoria degli algoritmi di ordinamento: Il mergesort ha un occupazione di memoria pari a 2n, mentre per tutti gli altri si ha n. Università degli Studi dell Aquila 27

28 Strutture dati fondamentali (tipi astratti) I tipi astratti sono strutture dati generali di particolare importanza in informatica. Tra di essi abbiamo: insiemi, liste, pile, code, matrici, alberi, grafi. Possiamo studiare le proprietà e le operazioni dei tipi di dato astratto indipendentemente dalla loro realizzazione tramite i tipi offerti dai linguaggi di programmazione Distinguiamo tra tipi astratti e tipi concreti: un tipo astratto può avere più rappresentazioni concrete. Ad esempio, possiamo studiare le liste in generale, ma poi implementarle con diverse tecniche: array statici, array dinamici, liste collegate con record e puntatori, etc. La programmazione con tipi astratti prevede la scrittura di programmi indipendentemente dalla rappresentazione utilizzata. Liste Le liste sono sequenze ordinate di elementi. Per sequenza ordinata si intende un insieme in cui è possibile riconoscere un primo elemento, un secondo, e così via. Si tratta quindi di un ordinamento sulle posizioni degli elementi e non sui loro valori. Quindi i valori all interno di una lista sono in generale disordinati, non rispettando alcun ordinamento particolare, crescente o decrescente. Introduciamo tre rappresentazioni per le liste: Rappresentazione con array Rappresentazione con liste collegate di record e puntatori Rappresentazione con liste collegate bidirezionali Rappresentazione con array Una lista può essere rappresentata con un array. È utile associare a quest ultimo un campo che indica il numero di elementi della lista. L occupazione di memoria è pari a n. Rappresentazione: const int D=100 ; typedef int vettore[d]; struct lista int n ; //numero valori lista vettore valori; //valori lista ; Considerazioni sulla complessità: Università degli Studi dell Aquila 28

29 L accesso a un elemento di una lista rappresentata con un array è ( 1). L inserimento di un elemento in una determinata posizione è (n) nel caso peggiore a causa dello spostamento degli altri elementi. Rappresentazione con liste collegate di record e puntatori Per ogni elemento, abbiamo bisogno di un record con campo valore e campo puntatore al record successivo. L occupazione di memoria è pari a 2n. struct elemento int valore; elemento* succ; ; typedef elemento* lista; //campo valore //campo puntatore al successivo Considerazioni sulla complessità: L accesso a un elemento di una lista collegata è (n) nel caso peggiore, perché bisogna scorrere la lista. L inserimento di un elemento dopo un certo elemento è ( 1), perché non è necessario spostare elementi. Rappresentazione con liste collegate bidirezionali Questa rappresentazione prevede un puntatore all elemento precedente, oltre al puntatore all elemento successivo. Può essere utile per scorrere facilmente la lista in entrambe le direzioni. L occupazione di memoria aumenta ed è pari a 3n. È necessario mantenere due puntatori iniziali, al primo e all ultimo elemento. l struct elemento int valore; elemento* succ; elemento* prec; ; typedef elemento* pelem; struct lista pelem primo; pelem ultimo; //campo valore //campo puntatore al successivo //campo puntatore al precedente Università degli Studi dell Aquila 29

30 ; Vediamo alcune funzioni, come CreaLista e StampaLista: void CreaLista (lista & l, int n) if (n==0) l.primo = NULL; l.ultimo = NULL; if (n>0) l.primo = new elemento; pelem p1; p1=l.primo; p1->prec=null; cout<<"elemento 0="; cin >> p1->valore; for (int i=1;i<n;i++) p1->succ=new elemento; p1->succ->prec=p1; p1=p1->succ; cout<<"elemento "<<i<<"="; cin >> p1->valore; p1->succ=null; l.ultimo=p1; void StampaLista (lista l) if (l.primo!=null) pelem p1=l.primo; while (p1!=null) cout<<p1->valore<<" "; p1=p1->succ ; La funzione StampaListaInv, che in versione iterativa per le liste collegate semplici aveva complessità ( n 2 ), per le liste bidirezionali è (n). void StampaListaInv (lista l) if (l.ultimo!=null) pelem p1=l.ultimo; Università degli Studi dell Aquila 30

31 while (p1!=null) cout<<p1->valore<<" "; p1=p1->prec ; Di seguito si riporta una versione ricorsiva per la creazione di una lista bidirezionale. Sono necessarie due funzioni: la funzione ricorsiva CreaListaRic è richiamata dalla funzione CreaLista: void CreaListaRic (pelem & p, pelem prec, int n, pelem & ultimo) if (n>0) p = new elemento; cin >> p->valore; p->prec=prec; CreaListaRic (p->succ,p,n-1,ultimo); p = NULL; ultimo=prec; void CreaLista (lista & l, int n) CreaListaRic (l.primo, NULL, n, l.ultimo); Operazioni elementari sulle liste Sulle liste non c è un modo univoco di definire le operazioni elementari. Si può seguire la strada di definire un insieme molto ristretto di operazioni, ma questo va spesso a scapito dell efficienza degli algoritmi su liste più complessi a seconda delle rappresentazioni. Un insieme minimale di operazioni può essere il seguente: Inserisci (x, pos, l): inserisce un nuovo elemento con valore x in posizione pos. Deve verificarsi che pos è compresa tra 0 e n. Per pos = 0 abbiamo un inserimento in testa. Per pos = n abbiamo un inserimento in coda. Cancella(pos, l): cancella l elemento in posizione pos, per pos compresa tra 0 e n-1. Per pos = 0 abbiamo la cancellazione in testa. Per pos=n-1 abbiamo la cancellazione in coda. Accedi(pos, l): restituisce il valore dell elemento in posizione pos. Init(l): inizializza una lista vuota. ListaVuota(l): effettua il test di lista vuota. Università degli Studi dell Aquila 31

32 È utile considerare anche le seguenti operazioni elementari per risolvere in maniera efficace alcuni problemi tipici: InsTesta(x, l): inserisce l elemento x in testa alla lista l; InsCoda(x,l): inserisce l elemento x in coda alla lista l; CancTesta(l): cancella l elemento di testa; CancCoda(l): cancella l elemento di coda; AccediTesta(l): restituisce l elemento di testa; AccediCoda(l): restituisce l elemento di coda; numelementi(l): restituisce il numero di elementi di una lista; Copia(l1,l2): copia la lista l1 nella lista l2; CancellaLista(l): cancella l intera lista l. Consideriamo i seguenti prototipi: void Inserisci(int x, int pos, lista & l); void Cancella(int pos, lista & l); int Accedi(int pos, lista l); lista Init(); bool ListaVuota(lista l); void InsTesta(int x, lista & l); void InsCoda(int x, lista & l); void CancTesta(lista & l); void CancCoda(lista & l); int AccediTesta(lista l); int AccediCoda(lista l); int numelementi(lista l); void Copia(lista l1, lista & l2); void CancellaLista(lista & l); Scriviamo alcune funzioni facendo uso delle sole operazioni elementari. La funzione CreaLista: lista CreaLista (int n) int x; lista l=init(); for (int i=0; i<n; i++) cin>>x; Inserisci(x,i,l); return l; La funzione CreaLista fa uso dell operazione Inserisci. Per la rappresentazione con array, scriviamo la funzione relativa: Università degli Studi dell Aquila 32

33 void Inserisci(int x, int pos, lista & l) //inserisce un elemento con valore x in posizione pos. pos è compresa tra 0 e n. Per pos =0 abbiamo un inserimento in testa. Per pos=n abbiamo un inserimento in coda. if (pos<0) cout << pos << "negativo"; if (pos>l.n) cout << pos << " troppo grande"; for (int i=l.n-1;i>=pos;i--) l.valori[i+1]= l.valori[i]; l.valori[pos]=x; //memorizzazione valore x in posizione p l.n++; La complessità nel caso peggiore (corrispondente all inserimento in testa) è (n), mentre nel caso migliore (corrispondente all inserimento in coda) è ( 1). Per la rappresentazione con liste collegate semplici, abbiamo la seguente funzione: void Inserisci(int x, int pos, lista & l) //inserisce un elemento con valore x in posizione pos. pos è compresa tra 0 e n. Per pos =0 abbiamo un inserimento in testa. Per pos=n abbiamo un inserimento in coda. if (pos<0) cout << pos << "negativo"; if (pos==0) elemento* p1=new elemento; p1->valore=x; p1->succ=l; l=p1; elemento* p=l ; for (int i=0 ; p!=null && i<(pos-1); i++) p=p->succ; if (p!=null) elemento * paux; paux=p->succ; p->succ=new elemento ; p=p->succ; p->valore=x ; p->succ=paux ; cout << pos << "troppo grande"; Università degli Studi dell Aquila 33

34 La complessità nel caso peggiore (corrispondente all inserimento in coda) è (n), mentre nel caso migliore (corrispondente all inserimento in testa) è ( 1). La complessità della funzione CreaLista con le due rappresentazioni: 1. nella rappresentazione con array, le chiamate ad Inserisci avvengono inserendo sempre in coda l elemento, che coincide con il caso migliore di Inserisci, pari a ( 1). Complessivamente la CreaLista ha tempo (n) ; 2. Nella rappresentazione con liste collegate, ogni chiamata di Inserisci corrisponde al caso peggiore per questa rappresentazione, cioè (n). Complessivamente si ha ( n 2 ). Nella rappresentazione con liste bidirezionali possiamo avere un miglioramento a patto che usiamo l operazione elementare InsCoda, che ha costo costante, al posto della generica Inserisci: void InsCoda(int x, lista & l) if (l.ultimo==null) l.primo = new elemento; l.primo->prec=null; l.primo->valore=x; l.primo->succ=null; l.ultimo=l.primo; l.ultimo->succ=new elemento; l.ultimo->succ->prec=l.ultimo; l.ultimo=l.ultimo->succ; l.ultimo->valore=x; l.ultimo->succ=null; La funzione CreaLista modificata ha costo lineare con la rappresentazione con liste bidirezionali: lista CreaLista (int n) int x; lista l=init(); for (int i=0; i<n; i++) cin>>x; InsCoda(x,l); return l; Università degli Studi dell Aquila 34

35 Altri esempi: invertire una lista, facendo uso di sole operazioni primitive: void InvertiLista(lista & l) lista l1=init(); int x; while(!listavuota(l)) x=acceditesta(l); CancTesta(l); InsTesta(x,l1); Copia(l1,l); CancellaLista(l1); Concatenare due liste, facendo uso di sole operazioni primitive: void ConcatenaListe(lista & l1, lista & l2, lista & l3) l3=init(); Copia(l1,l3); int x; while(!listavuota(l2)) x=acceditesta(l2); CancTesta(l2); InsCoda(x,l3); CancellaLista(l1); void Fusione(lista & l1, lista & l2, lista & l3) l3=init(); while (!ListaVuota(l1)&&!ListaVuota(l2)) if (AccediTesta(l1)<AccediTesta(l2)) InsCoda(AccediTesta(l1), l3); CancTesta(l1); InsCoda(AccediTesta(l2), l3); CancTesta(l2); Università degli Studi dell Aquila 35

36 while(!listavuota(l1)) InsCoda(AccediTesta(l1),l3); CancTesta(l1); while(!listavuota(l2)) InsCoda(AccediTesta(l2),l3); CancTesta(l2); Scrivere una funzione che, data una lista contenente valori ordinati in senso crescente, crei una nuova lista senza i valori ripetuti (per esempio, se la prima lista contiene i valori 2, 4, 4, 6, 7, 7, 8, al termine della funzione la seconda lista dovrà contenere i valori 2, 4, 6, 7, 8). La prima lista deve rimanere invariata. Si deve fare uso di sole operazioni primitive su liste. Qual è la complessità computazionale? void CreaSenzaRipetuti(lista l, lista & l1) int x=acceditesta(l); l1=init(); InsTesta(x,l1); for(int i=1;i<numelementi(l);i++) x=accedi(i,l); if (x!=accedicoda(l1)) InsCoda(x,l1); Nel caso della rappresentazione con array, le operazioni primitive utilizzate hanno tutte costo ( 1). Pertanto la complessità computazionale, determinata dal costo del ciclo, è (n). Nel caso della rappresentazione con liste collegate, le operazioni primitive presenti in questa funzione hanno un costo (n), determinando una complessità della funzione pari a ( n 2 ). Scrivere una funzione che, data una lista contenente valori ordinati in senso crescente, cancelli dalla lista i valori ripetuti (per esempio, se la lista contiene i valori 2, 4, 4, 6, 7, 7, 8, al termine della funzione la lista dovrà contenere i valori 2, 4, 6, 7, 8). Si deve fare uso di sole operazioni primitive su liste. Qual è la complessità computazionale? Soluzione a: void CancellaValoriRipetuti(lista & l) int x=acceditesta(l); lista l1=init(); InsTesta(x,l1); for(int i=1;i<numelementi(l);i++) Università degli Studi dell Aquila 36

37 x=accedi(i,l); if (x!=accedicoda(l1)) InsCoda(x,l1); CancellaLista(l); Copia(l1,l); Soluzione b: void CancellaValoriRipetuti(lista & l) int i=0; while (i<numelementi(l)-1) if (Accedi(i,l)==Accedi(i+1,l)) Cancella(i+1,l); i++; Data una lista, scrivere una funzione che trasferisca in una nuova lista gli elementi che contengono valori maggiori di un dato intero x. Pertanto la lista data non deve più contenere al termine della funzione gli elementi trasferiti. Inoltre la lista creata deve contenere i valori trasferiti nello stesso ordine in cui si trovavano nella lista data. Si deve fare uso di sole operazioni primitive su liste. Qual è la complessità computazionale? soluzione: void TrasferisciValoriMaggiori(lista & l, int x, lista & l1) int elem; lista l2=init(); while (!ListaVuota(l)) elem=acceditesta(l); if (elem>x) InsCoda(elem,l1); InsCoda(elem,l2); CancellaTesta(l); Copia(l2,l); CancellaLista(l2); Università degli Studi dell Aquila 37

38 Nel caso della rappresentazione con array, l operazione primitiva più costosa all interno del ciclo è CancellaTesta che ha costo (n). Pertanto la complessità computazionale, determinata dal costo del ciclo, è ( n 2 ). Nel caso della rappresentazione con liste collegate, l operazione primitiva più costosa all interno del ciclo è InsCoda che ha costo (n), determinando una complessità della funzione pari a ( n 2 ). Codifica operazioni primitive nella rappresentazione con array lista Init() lista l; l.n=0; return l; int Accedi(int pos, lista l) if (pos<0) cout << pos << "negativo"; if (pos>l.n) cout << pos << " troppo grande"; return l.valori[pos]; int AccediTesta(lista l) if (l.n==0) cout << "lista vuota"; return l.valori[0]; int AccediCoda(lista l) if (l.n==0) cout << "lista vuota"; return l.valori[l.n-1]; bool ListaVuota(lista l) return (l.n==0); Università degli Studi dell Aquila 38

39 void Inserisci(int x, int pos, lista & l) //inserisce un elemento con valore x in posizione pos. pos è //compresa tra 0 e n. Per pos =0 abbiamo un inserimento in //testa. Per pos=n abbiamo un inserimento in coda. if (pos<0) cout << pos << "negativo"; if (pos>l.n) cout << pos << " troppo grande"; for (int i=l.n-1;i>=pos;i--) l.valori[i+1]=l.valori[i]; l.valori[pos]=x; //memorizzazione valore x in //posizione p l.n++; void InsTesta(int x, lista & l) for (int i=l.n-1;i>=0;i--) l.valori[i+1]=l.valori[i]; l.valori[0]=x; //memorizzazione valore x in posizione 0 l.n++; void InsCoda(int x, lista & l) l.valori[l.n]=x; //memorizzazione valore x in posizione l.n l.n++; void Cancella(int pos, lista & l) if (l.n==0) cout << "lista vuota"; for (int i=pos;i<l.n-1;i++) l.valori[i]=l.valori[i+1]; l.n--; void CancTesta(lista & l) if (l.n==0) cout << "lista vuota"; Università degli Studi dell Aquila 39

40 for (int i=0;i<l.n-1;i++) l.valori[i]=l.valori[i+1]; l.n--; int numelementi(lista l) return l.n; void Copia(lista l1, lista & l2) for (int i=0;i<l1.n;i++) l2.valori[i]=l1.valori[i]; l2.n=l1.n; void CancellaLista(lista & l) l.n=0; Codifica operazioni primitive nella rappresentazione con liste collegate lista Init() lista l; l=null; return l; int Accedi(int pos, lista l) if (pos<0) cout << pos << "negativo"; if (pos==0) return l->valore; Università degli Studi dell Aquila 40

41 elemento* p=l ; for (int i=0 ; p!=null && i<pos; i++) p=p->succ; if (p!=null) return p->valore; cout << pos << "troppo grande"; int AccediTesta(lista l) if (l==null) cout << "lista vuota"; return l->valore; bool ListaVuota(lista l) return (l==null); void Inserisci(int x, int pos, lista & l) //inserisce un elemento con valore x in posizione pos. pos è compresa tra 0 e n. Per pos =0 abbiamo un inserimento in testa. Per pos=n abbiamo un inserimento in coda. if (pos<0) cout << pos << "negativo"; if (pos==0) elemento* p1=new elemento; p1->valore=x; p1->succ=l; l=p1; elemento* p=l ; for (int i=0 ; p!=null && i<(pos-1); i++) p=p->succ; if (p!=null) elemento* paux; paux=p->succ; Università degli Studi dell Aquila 41

42 p->succ=new elemento ; p=p->succ; p->valore=x ; p->succ=paux ; cout << pos << "troppo grande"; void InsTesta(int x, lista & l) elemento* p1=new elemento; p1->valore=x; p1->succ=l; l=p1; void InsCoda(int x, lista & l) if (l==null) //lista nulla l=new elemento; l->valore=x; l->succ=null; elemento* paux; paux=l; while (paux->succ!=null) paux=paux->succ; paux->succ=new elemento; paux=paux->succ; paux->valore=x; paux->succ=null; void CancTesta(lista & l) if (l!=null) elemento* paux=l; l=l->succ; delete paux; Università degli Studi dell Aquila 42

43 int numelementi(lista l) int i=0; while (l!=null) l=l->succ; i++; return i; void Copia(lista l1, lista & l2) if (l1==null) l2=null; l2 = new elemento; l2->valore=l1->valore; elemento *p1=l1->succ, *p2=l2; while (p1!=null) p2->succ=new elemento; p2=p2->succ; p2->valore=p1->valore; p1=p1->succ; p2->succ=null; void CancellaLista(lista & l) elemento *p=l; while (l!=null) l=l->succ; delete p; p=l; Università degli Studi dell Aquila 43

44 Pile e code Pile e code sono sequenze ordinate di elementi (come le liste) in cui si disciplina la strategia di accesso. La lettura di un elemento di queste strutture dati, così come la cancellazione di un elemento o l inserimento di un nuovo elemento, avvengono con delle regole ben precise. Pile Nella pila ( stack in inglese), l accesso è limitato ad una sola estremità della sequenza. Esiste quindi un elemento affiorante (l elemento top della pila) a cui è possibile accedere, mentre non è possibile accedere agli altri elementi, se non rimuovendo l elemento affiorante. L operazione di cancellazione dalla pila dell elemento affiorante si chiama pop, mentre l operazione di inserimento di un nuovo elemento al di sopra dell elemento affiorante si chiama push. Questa strategia di accesso per le pile va sotto il nome di LIFO (last in first out): l ultimo elemento ad entrare in una pila sarà il primo ad uscirne Le pile sono strutture dati molto comuni in informatica. Ad esempio, la gestione della memoria per le chiamate a funzioni avviene tramite uno stack di sistema. Nello stack sono depositate le informazioni relative alle chiamate di funzioni. L ultima funzione ad essere chiamata sarà quella affiorante nello stack. Ad esempio, nel caso di chiamate ricorsive, l ultima chiamata sarà anche la prima ad essere completata. In totale, possiamo definire cinque operazioni primitive su pile: Crea(p): inizializza una nuova pila p; Top(p): accede all elemento affiorante della pila p; Push(x,p): aggiunge un elemento x alla pila p; Pop(p): rimuove un elemento dalla pila p; Vuota(p): compie il test di pila vuota. Università degli Studi dell Aquila 44

45 Codifichiamo queste operazioni con le seguenti funzioni, supponendo di aver già dichiarato un tipo pila ed un tipo elemento : pila CreaPila(); elemento Top(pila p); void Push(elemento x, pila & p); void Pop(pila & p); bool PilaVuota(pila p); Con queste operazioni primitive, possiamo costruire qualsiasi algoritmo che opera su pile. Ad esempio, vogliamo leggere e cancellare l ultimo elemento di una pila. Allo scopo, abbiamo bisogno di una pila di appoggio: pila p=creapila(); //riempimento della pila p pila p1=creapila(); elemento x; while(!pilavuota(p)) x=top(p); Pop(p); Push(x,p1); x=top(p1); Stampa(x); Pop(p1); while(!pilavuota(p1)) x=top(p1); Pop(p1); Push(x,p); Università degli Studi dell Aquila 45

46 Rappresentazioni per le pile Le pile possono essere rappresentate in vari modi. Esaminiamo una rappresentazione con array e una con liste collegate. Rappresentazione con array 3 top const int D=100 ; typedef int elemento; //dipende dalla definizione dell elemento typedef elemento vettore[d]; struct pila int top ; //indice elemento top, se -1 pila vuota vettore elementi; //elementi pila ; Vediamo come le operazioni primitive sono implementate con questa rappresentazione: pila CreaPila() pila p; p.top=-1; return p; elemento Top(pila p) if (p.top==-1) cout<< Pila vuota ; return p.elementi[p.top]; void Push(elemento x, pila & p) if (p.top==d-1) cout<< Pila piena ; p.elementi[p.top+1]=x; Università degli Studi dell Aquila 46

47 p.top++; void Pop(pila & p) if (p.top==-1) cout<< Pila vuota ; p.top--; bool PilaVuota(pila p) return (p.top==-1); L operazione primitiva Push può dar luogo ad un errore se l array è tutto pieno. Scriviamo una funzione per la memorizzazione di n valori letti da tastiera in una pila: pila LeggiPila(int n) pila p; p=creapila(); elemento x; for (int i=0;i<n;i++) cout<<"elemento "<<i<<"="; cin >> x; Push(x,p); return p; Scriviamo una funzione per la stampa su video degli elementi di una pila. Notiamo che la funzione non svuota la pila perché il parametro è passato per valore: quindi la funzione svuota una copia della pila originaria. void ScriviPila(pila p) elemento x; while(!pilavuota(p)) x=top(p); cout << x << ; Pop(p); Università degli Studi dell Aquila 47

48 Rappresentazione con liste collegate typedef int elemento; //dipende dalla definizione dell elemento struct record elemento valore; record* succ; ; typedef record* pila; pila In questa rappresentazione, il puntatore iniziale alla lista punta all elemento affiorante della pila. Vediamo la codifica delle operazioni primitive con questa rappresentazione. pila CreaPila() pila p; p=null; return p; elemento Top(pila p) if (p==null) cout<< Pila vuota ; return p->valore; void Push(elemento x, pila & p) record* paux=new record; paux->valore=x; paux->succ=p; p=paux; void Pop(pila & p) if (p==null) cout<< Pila vuota ; record* paux=p; p=p->succ; delete paux ; bool PilaVuota(pila p) return (p==null); Università degli Studi dell Aquila 48

49 Con questa rappresentazione, la funzione scritta in precedenza per la stampa degli elementi di una pila non funziona correttamente dato che essa causa lo svuotamento della pila stessa. Non è infatti possibile effettuare la copia della lista collegata passando il parametro per valore. Quindi la funziona ScriviPila va riscritta, salvando gli elementi in una pila di appoggio man mano che vengono estratti dalla pila data, e poi ricostituendo la pila originaria: void ScriviPila(pila & p) elemento x; pila p1=creapila(); while(!pilavuota(p)) x=top(p); cout << x << " "; Pop(p); Push(x,p1); while(!pilavuota(p1)) x=top(p1); Pop(p1); Push(x,p); In entrambe le rappresentazioni viste, le operazioni primitive sulle pile hanno un tempo di esecuzione costante. La funzione ScriviPila ha un tempo di esecuzione lineare. Università degli Studi dell Aquila 49

50 Code Nelle code ( queue in inglese), l accesso in ingresso è limitato ad una estremità della sequenza, mentre l accesso in uscita all altra estremità. Dal lato in uscita, c è il solo elemento che è possibile esaminare (l elemento front della coda). L operazione di cancellazione dalla coda di tale elemento si chiama pop, mentre l operazione di inserimento di un nuovo elemento nell altra estremità si chiama push. Questa strategia di accesso per le code va sotto il nome di FIFO (first in first out): il primo elemento ad entrare in una coda sarà il primo ad uscirne Le code sono strutture dati molto comuni in informatica. Ad esempio, molte funzioni del sistema operativo per la gestione delle periferiche si basano sulle code. Varie richieste da più utenti o programmi per l uso di una stampante saranno gestite con una coda: la richiesta che arriva per prima sarà servita per prima. In totale, possiamo definire cinque operazioni primitive su code: Crea(c): inizializza una nuova coda c; Front(c): accede all elemento affiorante della coda c; Push(x,c): aggiunge un elemento x alla coda c; Pop(c): rimuove un elemento dalla coda c; Vuota(c): compie il test di coda vuota. Codifichiamo queste operazioni con le seguenti funzioni, supponendo di aver già dichiarato un tipo coda ed un tipo elemento : coda CreaCoda(); elemento Front(coda c); void Push(elemento x, coda & c); void Pop(coda & c); bool CodaVuota(coda c); Con queste operazioni primitive, possiamo costruire qualsiasi algoritmo che opera su code. Supponiamo di voler svuotare una coda e stampare gli elementi sul video: coda c=creacoda(); //riempimento della coda c elemento x; while(!codavuota(c)) x=front(c); Stampa(x); Pop(c); Università degli Studi dell Aquila 50

51 Rappresentazioni per le code Le pile possono essere rappresentate in vari modi. Esaminiamo due rappresentazioni con array e una con liste collegate. Prima rappresentazione con array Gli elementi sono inseriti alla fine del vettore ed estratti all inizio. Le due estremità sono indicate con due indici front e last. L indice front rappresenta l elemento da estrarre dalla coda e l indice last l ultimo elemento arrivato. Se l indice last è inferiore all indice front, si ha la coda vuota. Inizialmente, l indice last è posto a -1 e l indice front a 0. Quando l indice last raggiunge la fine dell array, è necessaria una traslazione all indietro di tutti gli elementi della coda front last const int D=100 ; typedef int elemento; //dipende dalla definizione dell elemento typedef elemento vettore[d]; struct coda int front ; //indice elemento front int last ; //indice elemento ultimo vettore elementi; //elementi coda ; Vediamo come le operazioni primitive sono implementate con questa rappresentazione: coda CreaCoda () coda c; c.last=-1; c.front=0; return c; elemento Front(coda c) if (c.last<c.front) cout<< Coda vuota ; return c.elementi[c.front]; Università degli Studi dell Aquila 51

Il tipo di dato astratto Pila

Il tipo di dato astratto Pila Il tipo di dato astratto Pila Il tipo di dato Pila Una pila è una sequenza di elementi (tutti dello stesso tipo) in cui l inserimento e l eliminazione di elementi avvengono secondo la regola seguente:

Dettagli

Due algoritmi di ordinamento. basati sulla tecnica Divide et Impera: Mergesort e Quicksort

Due algoritmi di ordinamento. basati sulla tecnica Divide et Impera: Mergesort e Quicksort Due algoritmi di ordinamento basati sulla tecnica Divide et Impera: Mergesort e Quicksort (13 ottobre 2009, 2 novembre 2010) Ordinamento INPUT: un insieme di n oggetti a 1, a 2,, a n presi da un dominio

Dettagli

10 - Programmare con gli Array

10 - Programmare con gli Array 10 - Programmare con gli Array Programmazione e analisi di dati Modulo A: Programmazione in Java Paolo Milazzo Dipartimento di Informatica, Università di Pisa http://www.di.unipi.it/ milazzo milazzo di.unipi.it

Dettagli

GESTIONE INFORMATICA DEI DATI AZIENDALI

GESTIONE INFORMATICA DEI DATI AZIENDALI GESTIONE INFORMATICA DEI DATI AZIENDALI Alberto ZANONI Centro Vito Volterra Università Tor Vergata Via Columbia 2, 00133 Roma, Italy zanoni@volterra.uniroma2.it Rudimenti di programmazione Programming

Dettagli

Corso di Tecniche di Programmazione

Corso di Tecniche di Programmazione Corso di Tecniche di Programmazione Corsi di Laurea in Ingegneria Informatica ed Automatica Anno Accedemico 003/004 Proff. Giuseppe De Giacomo, Luca Iocchi, Domenico Lembo Dispensa : Algoritmi di Ordinamento

Dettagli

La struttura dati ad albero binario

La struttura dati ad albero binario La struttura dati ad albero binario L albero è una struttura dati nella quale le informazioni sono organizzate in modo gerarchico, dall alto verso il basso. Gli elementi di un albero si chiamano nodi,

Dettagli

Algoritmi e strutture dati. Codici di Huffman

Algoritmi e strutture dati. Codici di Huffman Algoritmi e strutture dati Codici di Huffman Memorizzazione dei dati Quando un file viene memorizzato, esso va memorizzato in qualche formato binario Modo più semplice: memorizzare il codice ASCII per

Dettagli

AA 2006-07 LA RICORSIONE

AA 2006-07 LA RICORSIONE PROGRAMMAZIONE AA 2006-07 LA RICORSIONE AA 2006-07 Prof.ssa A. Lanza - DIB 1/18 LA RICORSIONE Il concetto di ricorsione nasce dalla matematica Una funzione matematica è definita ricorsivamente quando nella

Dettagli

Esercizi per il corso di Algoritmi e Strutture Dati

Esercizi per il corso di Algoritmi e Strutture Dati 1 Esercizi per il corso di Algoritmi e Strutture Dati Esercizi sulla Tecnica Divide et Impera N.B. Tutti gli algoritmi vanno scritti in pseudocodice (non in Java, né in C++, etc. ). Di tutti gli algoritmi

Dettagli

SOMMARIO Coda (queue): QUEUE. QUEUE : specifica QUEUE

SOMMARIO Coda (queue): QUEUE. QUEUE : specifica QUEUE SOMMARIO Coda (queue): Specifica: interfaccia. Implementazione: Strutture indicizzate (array): Array di dimensione variabile. Array circolari. Strutture collegate (nodi). Prestazioni. Strutture Software

Dettagli

Algoritmi di Ricerca. Esempi di programmi Java

Algoritmi di Ricerca. Esempi di programmi Java Fondamenti di Informatica Algoritmi di Ricerca Esempi di programmi Java Fondamenti di Informatica - D. Talia - UNICAL 1 Ricerca in una sequenza di elementi Data una sequenza di elementi, occorre verificare

Dettagli

Sono casi particolari di MCF : SPT (cammini minimi) non vi sono vincoli di capacità superiore (solo x ij > 0) (i, j) A : c ij, costo di percorrenza

Sono casi particolari di MCF : SPT (cammini minimi) non vi sono vincoli di capacità superiore (solo x ij > 0) (i, j) A : c ij, costo di percorrenza Il problema di flusso di costo minimo (MCF) Dati : grafo orientato G = ( N, A ) i N, deficit del nodo i : b i (i, j) A u ij, capacità superiore (max quantità di flusso che può transitare) c ij, costo di

Dettagli

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2 Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2 Dispensa E08 Soluzione Esercizi F. Gasparetti, C. Limongelli Marzo 2008 http://www.dia.uniroma3.it/~java/fondinf1/ Soluzione Esercizi

Dettagli

Ricerche, ordinamenti e fusioni. 5.1 Introduzione. 5.2 Ricerca completa

Ricerche, ordinamenti e fusioni. 5.1 Introduzione. 5.2 Ricerca completa Ricerche, ordinamenti e fusioni 5.1 Introduzione Questo capitolo ci permette di fare pratica di programmazione utilizzando gli strumenti del linguaggio introdotti finora. A una prima lettura possono essere

Dettagli

Strutture. Strutture e Unioni. Definizione di strutture (2) Definizione di strutture (1)

Strutture. Strutture e Unioni. Definizione di strutture (2) Definizione di strutture (1) Strutture Strutture e Unioni DD cap.10 pp.379-391, 405-406 KP cap. 9 pp.361-379 Strutture Collezioni di variabili correlate (aggregati) sotto un unico nome Possono contenere variabili con diversi nomi

Dettagli

void funzioneprova() { int x=2; cout<<"dentro la funzione x="<<x<<endl; }

void funzioneprova() { int x=2; cout<<dentro la funzione x=<<x<<endl; } FUNZIONI 57. Cosa servono le funzioni? A spezzare il programma in diverse parti relativamente indipendenti fra loro, ovvero interagenti sono attraverso i parametri di input ed IL VALORE di uscita. In questo

Dettagli

PROBLEMA DELLA RICERCA DI UN ELEMENTO IN UN ARRAY E ALGORITMI RISOLUTIVI

PROBLEMA DELLA RICERCA DI UN ELEMENTO IN UN ARRAY E ALGORITMI RISOLUTIVI PROBLEMA DELLA RICERCA DI UN ELEMENTO IN UN ARRAY E ALGORITMI RISOLUTIVI PROBLEMA DELLA RICERCA in termini generali: Dati in input un insieme S di elementi (numeri, caratteri, stringhe, ) e un elemento

Dettagli

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI Indice 1 Le frazioni algebriche 1.1 Il minimo comune multiplo e il Massimo Comun Divisore fra polinomi........ 1. Le frazioni algebriche....................................

Dettagli

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati schifano@fe.infn.it Laurea di Informatica - Università di Ferrara 2011-2012 [1] Strutture dati Dinamiche: Le liste Una lista è una sequenza di elementi di un certo tipo in cui è possibile aggiungere e/o

Dettagli

1. PRIME PROPRIETÀ 2

1. PRIME PROPRIETÀ 2 RELAZIONI 1. Prime proprietà Il significato comune del concetto di relazione è facilmente intuibile: due elementi sono in relazione se c è un legame tra loro descritto da una certa proprietà; ad esempio,

Dettagli

Corso di Informatica

Corso di Informatica Corso di Informatica Modulo T Scorrimento-Rotazione-Ricerca Prerequisiti Programmazione elementare Conoscenza ed uso di vettori Introduzione Lo scopo di questa Unità è approfondire il concetto di vettore

Dettagli

Funzioni in C. Violetta Lonati

Funzioni in C. Violetta Lonati Università degli studi di Milano Dipartimento di Scienze dell Informazione Laboratorio di algoritmi e strutture dati Corso di laurea in Informatica Funzioni - in breve: Funzioni Definizione di funzioni

Dettagli

I tipi di dato astratti

I tipi di dato astratti I tipi di dato astratti.0 I tipi di dato astratti c Diego Calvanese Fondamenti di Informatica Corso di Laurea in Ingegneria Elettronica A.A. 001/00.0 0 I tipi di dato astratti La nozione di tipo di dato

Dettagli

Programmazione dinamica

Programmazione dinamica Capitolo 6 Programmazione dinamica 6.4 Il problema della distanza di edit tra due stringhe x e y chiede di calcolare il minimo numero di operazioni su singoli caratteri (inserimento, cancellazione e sostituzione)

Dettagli

Dimensione di uno Spazio vettoriale

Dimensione di uno Spazio vettoriale Capitolo 4 Dimensione di uno Spazio vettoriale 4.1 Introduzione Dedichiamo questo capitolo ad un concetto fondamentale in algebra lineare: la dimensione di uno spazio vettoriale. Daremo una definizione

Dettagli

4 3 4 = 4 x 10 2 + 3 x 10 1 + 4 x 10 0 aaa 10 2 10 1 10 0

4 3 4 = 4 x 10 2 + 3 x 10 1 + 4 x 10 0 aaa 10 2 10 1 10 0 Rappresentazione dei numeri I numeri che siamo abituati ad utilizzare sono espressi utilizzando il sistema di numerazione decimale, che si chiama così perché utilizza 0 cifre (0,,2,3,4,5,6,7,8,9). Si dice

Dettagli

Complessità Computazionale

Complessità Computazionale Complessità Computazionale Analisi Algoritmi e pseudocodice Cosa significa analizzare un algoritmo Modello di calcolo Analisi del caso peggiore e del caso medio Esempio di algoritmo in pseudocodice INSERTION

Dettagli

4.1 Modelli di calcolo analisi asintotica e ricorrenze

4.1 Modelli di calcolo analisi asintotica e ricorrenze 4 Esercizi Prima Parte 4.1 Modelli di calcolo analisi asintotica e ricorrenze Esercizio 4 1 Rispondere alle seguenti domande: 1. Come misuriamo l efficienza di un algoritmo?. Quali sono gli algoritmi più

Dettagli

Esercizi Capitolo 6 - Alberi binari di ricerca

Esercizi Capitolo 6 - Alberi binari di ricerca Esercizi Capitolo 6 - Alberi binari di ricerca Alberto Montresor 23 settembre 200 Alcuni degli esercizi che seguono sono associati alle rispettive soluzioni. Se il vostro lettore PDF lo consente, è possibile

Dettagli

Note su quicksort per ASD 2010-11 (DRAFT)

Note su quicksort per ASD 2010-11 (DRAFT) Note su quicksort per ASD 010-11 (DRAFT) Nicola Rebagliati 7 dicembre 010 1 Quicksort L algoritmo di quicksort è uno degli algoritmi più veloci in pratica per il riordinamento basato su confronti. L idea

Dettagli

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A. 2013-14. Pietro Frasca.

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A. 2013-14. Pietro Frasca. Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A. 2013-14 Pietro Frasca Lezione 11 Martedì 12-11-2013 1 Tecniche di allocazione mediante free list Generalmente,

Dettagli

ESERCIZI DI PROBLEM SOLVING E COMPOSIZIONE DEI DIAGRAMMI DI FLUSSO per le classi terza

ESERCIZI DI PROBLEM SOLVING E COMPOSIZIONE DEI DIAGRAMMI DI FLUSSO per le classi terza ESERCIZI DI PROBLEM SOLVING E COMPOSIZIONE DEI DIAGRAMMI DI FLUSSO per le classi terza vers.3 in lavorazione Docente SAFFI FABIO Contenuti 01.Esercizi generici sul diagramma di flusso - flow chart... 2

Dettagli

Matematica generale CTF

Matematica generale CTF Successioni numeriche 19 agosto 2015 Definizione di successione Monotonìa e limitatezza Forme indeterminate Successioni infinitesime Comportamento asintotico Criterio del rapporto per le successioni Definizione

Dettagli

Corrispondenze e funzioni

Corrispondenze e funzioni Corrispondenze e funzioni L attività fondamentale della mente umana consiste nello stabilire corrispondenze e relazioni tra oggetti; è anche per questo motivo che il concetto di corrispondenza è uno dei

Dettagli

FONDAMENTI di INFORMATICA L. Mezzalira

FONDAMENTI di INFORMATICA L. Mezzalira FONDAMENTI di INFORMATICA L. Mezzalira Possibili domande 1 --- Caratteristiche delle macchine tipiche dell informatica Componenti hardware del modello funzionale di sistema informatico Componenti software

Dettagli

Plate Locator Riconoscimento Automatico di Targhe

Plate Locator Riconoscimento Automatico di Targhe Progetto per Laboratorio di Informatica 3 - Rimotti Daniele, Santinelli Gabriele Plate Locator Riconoscimento Automatico di Targhe Il programma plate_locator.m prende come input: l immagine della targa

Dettagli

Esempio: dest = parolagigante, lettere = PROVA dest (dopo l'invocazione di tipo pari ) = pprrlogvgante

Esempio: dest = parolagigante, lettere = PROVA dest (dopo l'invocazione di tipo pari ) = pprrlogvgante Esercizio 0 Scambio lettere Scrivere la funzione void scambiolettere(char *dest, char *lettere, int p_o_d) che modifichi la stringa destinazione (dest), sostituendone i caratteri pari o dispari (a seconda

Dettagli

B+Trees. Introduzione

B+Trees. Introduzione B+Trees Introduzione B+Trees Il B+Trees e la variante maggiormente utilizzata dei BTrees BTrees e B+trees fanno parte della famiglia degli alberi di ricerca. Nel B+Trees i dati sono memorizzati solo nelle

Dettagli

INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI

INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI Prima di riuscire a scrivere un programma, abbiamo bisogno di conoscere un metodo risolutivo, cioè un metodo che a partire dai dati di ingresso fornisce i risultati attesi.

Dettagli

Strutturazione logica dei dati: i file

Strutturazione logica dei dati: i file Strutturazione logica dei dati: i file Informazioni più complesse possono essere composte a partire da informazioni elementari Esempio di una banca: supponiamo di voler mantenere all'interno di un computer

Dettagli

Appunti sulla Macchina di Turing. Macchina di Turing

Appunti sulla Macchina di Turing. Macchina di Turing Macchina di Turing Una macchina di Turing è costituita dai seguenti elementi (vedi fig. 1): a) una unità di memoria, detta memoria esterna, consistente in un nastro illimitato in entrambi i sensi e suddiviso

Dettagli

Soluzione dell esercizio del 2 Febbraio 2004

Soluzione dell esercizio del 2 Febbraio 2004 Soluzione dell esercizio del 2 Febbraio 2004 1. Casi d uso I casi d uso sono riportati in Figura 1. Figura 1: Diagramma dei casi d uso. E evidenziato un sotto caso di uso. 2. Modello concettuale Osserviamo

Dettagli

INFORMATICA 1 L. Mezzalira

INFORMATICA 1 L. Mezzalira INFORMATICA 1 L. Mezzalira Possibili domande 1 --- Caratteristiche delle macchine tipiche dell informatica Componenti hardware del modello funzionale di sistema informatico Componenti software del modello

Dettagli

Introduzione alla programmazione in C

Introduzione alla programmazione in C Introduzione alla programmazione in C Testi Consigliati: A. Kelley & I. Pohl C didattica e programmazione B.W. Kernighan & D. M. Ritchie Linguaggio C P. Tosoratti Introduzione all informatica Materiale

Dettagli

Definire all'interno del codice un vettore di interi di dimensione DIM, es. int array[] = {1, 5, 2, 4, 8, 1, 1, 9, 11, 4, 12};

Definire all'interno del codice un vettore di interi di dimensione DIM, es. int array[] = {1, 5, 2, 4, 8, 1, 1, 9, 11, 4, 12}; ESERCIZI 2 LABORATORIO Problema 1 Definire all'interno del codice un vettore di interi di dimensione DIM, es. int array[] = {1, 5, 2, 4, 8, 1, 1, 9, 11, 4, 12}; Chiede all'utente un numero e, tramite ricerca

Dettagli

COGNOME E NOME (IN STAMPATELLO) MATRICOLA

COGNOME E NOME (IN STAMPATELLO) MATRICOLA Politecnico di Milano Facoltà di Ingegneria dell Informazione Informatica 3 Proff. Ghezzi, Lanzi, Matera e Morzenti Seconda prova in itinere 4 Luglio 2005 COGNOME E NOME (IN STAMPATELLO) MATRICOLA Risolvere

Dettagli

Corso di Matematica per la Chimica

Corso di Matematica per la Chimica Dott.ssa Maria Carmela De Bonis a.a. 203-4 I sistemi lineari Generalità sui sistemi lineari Molti problemi dell ingegneria, della fisica, della chimica, dell informatica e dell economia, si modellizzano

Dettagli

Laboratorio di programmazione

Laboratorio di programmazione Laboratorio di programmazione Lezione VI Tatiana Zolo tatiana.zolo@libero.it 1 LE STRUCT Tipo definito dall utente i cui elementi possono essere eterogenei (di tipo diverso). Introduce un nuovo tipo di

Dettagli

Concetto di Funzione e Procedura METODI in Java

Concetto di Funzione e Procedura METODI in Java Fondamenti di Informatica Concetto di Funzione e Procedura METODI in Java Fondamenti di Informatica - D. Talia - UNICAL 1 Metodi e Sottoprogrammi Mentre in Java tramite le classi e gli oggetti è possibile

Dettagli

Sequenziamento a minimo costo di commutazione in macchine o celle con costo lineare e posizione home (In generale il metodo di ottimizzazione

Sequenziamento a minimo costo di commutazione in macchine o celle con costo lineare e posizione home (In generale il metodo di ottimizzazione Sequenziamento a minimo costo di commutazione in macchine o celle con costo lineare e posizione home (In generale il metodo di ottimizzazione presentato in questo file trova la seq. a costo minimo per

Dettagli

A intervalli regolari ogni router manda la sua tabella a tutti i vicini, e riceve quelle dei vicini.

A intervalli regolari ogni router manda la sua tabella a tutti i vicini, e riceve quelle dei vicini. Algoritmi di routing dinamici (pag.89) UdA2_L5 Nelle moderne reti si usano algoritmi dinamici, che si adattano automaticamente ai cambiamenti della rete. Questi algoritmi non sono eseguiti solo all'avvio

Dettagli

Testi di Esercizi e Quesiti 1

Testi di Esercizi e Quesiti 1 Architettura degli Elaboratori, 2009-2010 Testi di Esercizi e Quesiti 1 1. Una rete logica ha quattro variabili booleane di ingresso a 0, a 1, b 0, b 1 e due variabili booleane di uscita z 0, z 1. La specifica

Dettagli

Esercizi su. Funzioni

Esercizi su. Funzioni Esercizi su Funzioni ๒ Varie Tracce extra Sul sito del corso ๓ Esercizi funz_max.cc funz_fattoriale.cc ๔ Documentazione Il codice va documentato (commentato) Leggibilità Riduzione degli errori Manutenibilità

Dettagli

RICERCA DI UN ELEMENTO

RICERCA DI UN ELEMENTO RICERCA DI UN ELEMENTO Si legga da tastiera un array di N elementi (N stabilito dall utente) Si richieda un elemento x il programma deve cercare l elemento x nell array Se l elemento è presente, deve visualizzare

Dettagli

Algebra di Boole: Concetti di base. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

Algebra di Boole: Concetti di base. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica Fondamenti di Informatica Algebra di Boole: Concetti di base Fondamenti di Informatica - D. Talia - UNICAL 1 Algebra di Boole E un algebra basata su tre operazioni logiche OR AND NOT Ed operandi che possono

Dettagli

Ricerca Operativa Esercizi sul metodo del simplesso. Luigi De Giovanni, Laura Brentegani

Ricerca Operativa Esercizi sul metodo del simplesso. Luigi De Giovanni, Laura Brentegani Ricerca Operativa Esercizi sul metodo del simplesso Luigi De Giovanni, Laura Brentegani 1 1) Risolvere il seguente problema di programmazione lineare. ma + + 3 s.t. 2 + + 2 + 2 + 3 5 2 + 2 + 6,, 0 Soluzione.

Dettagli

I file di dati. Unità didattica D1 1

I file di dati. Unità didattica D1 1 I file di dati Unità didattica D1 1 1) I file sequenziali Utili per la memorizzazione di informazioni testuali Si tratta di strutture organizzate per righe e non per record Non sono adatte per grandi quantità

Dettagli

Corso di Informatica

Corso di Informatica Corso di Informatica Modulo T3 1-Sottoprogrammi 1 Prerequisiti Tecnica top-down Programmazione elementare 2 1 Introduzione Lo scopo di questa Unità è utilizzare la metodologia di progettazione top-down

Dettagli

Una funzione è detta ricorsiva se chiama, direttamente o indirettamente, se stessa. In C tutte le funzioni possono essere usate ricorsivamente.

Una funzione è detta ricorsiva se chiama, direttamente o indirettamente, se stessa. In C tutte le funzioni possono essere usate ricorsivamente. Ricorsione Funzioni ricorsive Una funzione è detta ricorsiva se chiama, direttamente o indirettamente, se stessa. In C tutte le funzioni possono essere usate ricorsivamente. Un esempio di funzione ricorsiva

Dettagli

Informatica 3. LEZIONE 21: Ricerca su liste e tecniche di hashing. Modulo 1: Algoritmi sequenziali e basati su liste Modulo 2: Hashing

Informatica 3. LEZIONE 21: Ricerca su liste e tecniche di hashing. Modulo 1: Algoritmi sequenziali e basati su liste Modulo 2: Hashing Informatica 3 LEZIONE 21: Ricerca su liste e tecniche di hashing Modulo 1: Algoritmi sequenziali e basati su liste Modulo 2: Hashing Informatica 3 Lezione 21 - Modulo 1 Algoritmi sequenziali e basati su

Dettagli

Le query di raggruppamento

Le query di raggruppamento Le query di raggruppamento Le "Query di raggruppamento" sono delle Query di selezione che fanno uso delle "Funzioni di aggregazione" come la Somma, il Conteggio, il Massimo, il Minimo o la Media, per visualizzare

Dettagli

Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi.

Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi. Algoritmi 1 Sommario Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi. 2 Informatica Nome Informatica=informazione+automatica. Definizione Scienza che si occupa dell

Dettagli

STRUTTURE NON LINEARI

STRUTTURE NON LINEARI PR1 Lezione 13: STRUTTURE NON LINEARI Michele Nappi mnappi@unisa.it www.dmi.unisa.it/people/nappi Per la realizzazione della presentazione è stato utilizzato in parte materiale didattico prodotto da Oronzo

Dettagli

Matematica in laboratorio

Matematica in laboratorio Unità 1 Attività guidate Attività 1 Foglio elettronico Divisibilità tra numeri naturali Costruisci un foglio di lavoro per determinare se a è divisibile per b, essendo a e b due numeri naturali, con a

Dettagli

Capitolo 2. Operazione di limite

Capitolo 2. Operazione di limite Capitolo 2 Operazione di ite In questo capitolo vogliamo occuparci dell operazione di ite, strumento indispensabile per scoprire molte proprietà delle funzioni. D ora in avanti riguarderemo i domini A

Dettagli

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto: Tipi primitivi Il linguaggio Java offre alcuni tipi di dato primitivi Una variabile di tipo primitivo può essere utilizzata direttamente. Non è un riferimento e non ha senso tentare di istanziarla mediante

Dettagli

Risolvere un problema significa individuare un procedimento che permetta di arrivare al risultato partendo dai dati

Risolvere un problema significa individuare un procedimento che permetta di arrivare al risultato partendo dai dati Algoritmi Algoritmi Risolvere un problema significa individuare un procedimento che permetta di arrivare al risultato partendo dai dati Il procedimento (chiamato algoritmo) è composto da passi elementari

Dettagli

Informatica 3. LEZIONE 23: Indicizzazione. Modulo 1: Indicizzazione lineare, ISAM e ad albero Modulo 2: 2-3 trees, B-trees e B + -trees

Informatica 3. LEZIONE 23: Indicizzazione. Modulo 1: Indicizzazione lineare, ISAM e ad albero Modulo 2: 2-3 trees, B-trees e B + -trees Informatica 3 LEZIONE 23: Indicizzazione Modulo 1: Indicizzazione lineare, ISAM e ad albero Modulo 2: 2-3 trees, B-trees e B + -trees Informatica 3 Lezione 23 - Modulo 1 Indicizzazione lineare, ISAM e

Dettagli

RICORSIVITA. Vediamo come si programma la soluzione ricorsiva al problema precedente: Poniamo S 1 =1 S 2 =1+2 S 3 =1+2+3

RICORSIVITA. Vediamo come si programma la soluzione ricorsiva al problema precedente: Poniamo S 1 =1 S 2 =1+2 S 3 =1+2+3 RICORSIVITA 1. Cos è la ricorsività? La ricorsività è un metodo di soluzione dei problemi che consiste nell esprimere la soluzione relativa al caso n in funzione della soluzione relativa al caso n-1. La

Dettagli

Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori

Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori Gli array Array e puntatori Laboratorio di Informatica I un array è un insieme di elementi (valori) avente le seguenti caratteristiche: - un array è ordinato: agli elementi dell array è assegnato un ordine

Dettagli

Calcolare il massimo di una lista

Calcolare il massimo di una lista Calcolare il massimo di una lista Ieri abbiamo imparato a calcolare il massimo di una lista predefinita: lista = [4,24,-89,81,3,0,-12,31] max = lista[0] # questo e' un commento: primo elemento di lista

Dettagli

Esercizi Capitolo 2 - Analisi di Algoritmi

Esercizi Capitolo 2 - Analisi di Algoritmi Esercizi Capitolo - Analisi di Algoritmi Alberto Montresor 19 Agosto, 014 Alcuni degli esercizi che seguono sono associati alle rispettive soluzioni. Se il vostro lettore PDF lo consente, è possibile saltare

Dettagli

La distribuzione Normale. La distribuzione Normale

La distribuzione Normale. La distribuzione Normale La Distribuzione Normale o Gaussiana è la distribuzione più importante ed utilizzata in tutta la statistica La curva delle frequenze della distribuzione Normale ha una forma caratteristica, simile ad una

Dettagli

Alessandro Pellegrini

Alessandro Pellegrini Esercitazione sulle Rappresentazioni Numeriche Esistono 1 tipi di persone al mondo: quelli che conoscono il codice binario e quelli che non lo conoscono Alessandro Pellegrini Cosa studiare prima Conversione

Dettagli

Cluster. Vicino alla temperatura critica gli spin formano grandi gruppi (cluster)

Cluster. Vicino alla temperatura critica gli spin formano grandi gruppi (cluster) Cluster Vicino alla temperatura critica gli spin formano grandi gruppi (cluster) all interno di ogni gruppo è molto improbabile riuscire a flippare uno spin perché ci sarebbe una grande perdita di energia,

Dettagli

Algoritmi e diagrammi di flusso

Algoritmi e diagrammi di flusso Algoritmi e diagrammi di flusso Un algoritmo può essere descritto come una sequenza finita ed ordinata di operazioni che descrivono la soluzione di un problema. Per sequenza finita si intende che un algoritmo

Dettagli

Università degli Studi di Ferrara - A.A. 2014/15 Dott. Valerio Muzzioli ORDINAMENTO DEI DATI

Università degli Studi di Ferrara - A.A. 2014/15 Dott. Valerio Muzzioli ORDINAMENTO DEI DATI ORDINAMENTO DEI DATI Quando si ordina un elenco (ovvero una serie di righe contenenti dati correlati), le righe sono ridisposte in base al contenuto di una colonna specificata. Distinguiamo due tipi di

Dettagli

ALGEBRA DELLE PROPOSIZIONI

ALGEBRA DELLE PROPOSIZIONI Università di Salerno Fondamenti di Informatica Corso di Laurea Ingegneria Corso B Docente: Ing. Giovanni Secondulfo Anno Accademico 2010-2011 ALGEBRA DELLE PROPOSIZIONI Fondamenti di Informatica Algebra

Dettagli

Laboratorio di Calcolatori 1 Corso di Laurea in Fisica A.A. 2006/2007

Laboratorio di Calcolatori 1 Corso di Laurea in Fisica A.A. 2006/2007 Laboratorio di Calcolatori 1 Corso di Laurea in Fisica A.A. 2006/2007 Dott.Davide Di Ruscio Dipartimento di Informatica Università degli Studi di L Aquila Lezione del 08/03/07 Nota Questi lucidi sono tratti

Dettagli

Esempi di algoritmi. Lezione III

Esempi di algoritmi. Lezione III Esempi di algoritmi Lezione III Scopo della lezione Implementare da zero algoritmi di media complessità. Verificare la correttezza di un algoritmo eseguendolo a mano. Imparare a valutare le prestazioni

Dettagli

Introduzione al MATLAB c Parte 2

Introduzione al MATLAB c Parte 2 Introduzione al MATLAB c Parte 2 Lucia Gastaldi Dipartimento di Matematica, http://dm.ing.unibs.it/gastaldi/ 18 gennaio 2008 Outline 1 M-file di tipo Script e Function Script Function 2 Costrutti di programmazione

Dettagli

Algoritmi su array / 2

Algoritmi su array / 2 Corso di Informatica Algoritmi su array / Anno Accademico / Francesco Tortorella Algoritmi su array Operazioni tipiche sugli array: inizializzazione lettura stampa ricerca del minimo e del massimo ricerca

Dettagli

Analisi di scenario File Nr. 10

Analisi di scenario File Nr. 10 1 Analisi di scenario File Nr. 10 Giorgio Calcagnini Università di Urbino Dip. Economia, Società, Politica giorgio.calcagnini@uniurb.it http://www.econ.uniurb.it/calcagnini/ http://www.econ.uniurb.it/calcagnini/forecasting.html

Dettagli

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo. DALLE PESATE ALL ARITMETICA FINITA IN BASE 2 Si è trovato, partendo da un problema concreto, che con la base 2, utilizzando alcune potenze della base, operando con solo addizioni, posso ottenere tutti

Dettagli

4. Operazioni elementari per righe e colonne

4. Operazioni elementari per righe e colonne 4. Operazioni elementari per righe e colonne Sia K un campo, e sia A una matrice m n a elementi in K. Una operazione elementare per righe sulla matrice A è una operazione di uno dei seguenti tre tipi:

Dettagli

Informatica 3. Informatica 3. LEZIONE 10: Introduzione agli algoritmi e alle strutture dati. Lezione 10 - Modulo 1. Importanza delle strutture dati

Informatica 3. Informatica 3. LEZIONE 10: Introduzione agli algoritmi e alle strutture dati. Lezione 10 - Modulo 1. Importanza delle strutture dati Informatica 3 Informatica 3 LEZIONE 10: Introduzione agli algoritmi e alle strutture dati Modulo 1: Perchè studiare algoritmi e strutture dati Modulo 2: Definizioni di base Lezione 10 - Modulo 1 Perchè

Dettagli

Corso di Fondamenti di Informatica Algoritmi su array / 2

Corso di Fondamenti di Informatica Algoritmi su array / 2 Corso di Fondamenti di Informatica Algoritmi su array / Anno Accademico 00/009 Francesco Tortorella Algoritmi su array Operazioni tipiche sugli array: inizializzazione lettura stampa ricerca del minimo

Dettagli

Allocazione dinamica della memoria - riepilogo

Allocazione dinamica della memoria - riepilogo Università degli studi di Milano Dipartimento di Scienze dell Informazione Laboratorio di algoritmi e strutture dati Corso di laurea in Informatica In breve Storage duration Allocazione dinamica della

Dettagli

13. Campi vettoriali

13. Campi vettoriali 13. Campi vettoriali 1 Il campo di velocità di un fluido Il concetto di campo in fisica non è limitato ai fenomeni elettrici. In generale il valore di una grandezza fisica assegnato per ogni punto dello

Dettagli

1 Applicazioni Lineari tra Spazi Vettoriali

1 Applicazioni Lineari tra Spazi Vettoriali 1 Applicazioni Lineari tra Spazi Vettoriali Definizione 1 (Applicazioni lineari) Si chiama applicazione lineare una applicazione tra uno spazio vettoriale ed uno spazio vettoriale sul campo tale che "!$%!

Dettagli

Appunti tratti dal videocorso on-line di Algoritmi e Programmazione Avanzata By ALeXio

Appunti tratti dal videocorso on-line di Algoritmi e Programmazione Avanzata By ALeXio Appunti tratti dal videocorso on-line di Algoritmi e Programmazione Avanzata By ALeXio 1-La memoria dinamica La scrittura di un programma (indipendentemente dal linguaggio adottato) deve sempre tener conto

Dettagli

3 GRAFICI DI FUNZIONI

3 GRAFICI DI FUNZIONI 3 GRAFICI DI FUNZIONI Particolari sottoinsiemi di R che noi studieremo sono i grafici di funzioni. Il grafico di una funzione f (se non è specificato il dominio di definizione) è dato da {(x, y) : x dom

Dettagli

Le stringhe. Le stringhe

Le stringhe. Le stringhe Informatica: C++ Gerboni Roberta Stringhe di caratteri (esempi di utilizzo dei vettori) Nel linguaggio C++ una stringa è semplicemente un vettore di caratteri Vettori di caratteri La stringa "hello" è

Dettagli

MODULO 5 ACCESS Basi di dati. Lezione 4

MODULO 5 ACCESS Basi di dati. Lezione 4 MODULO 5 ACCESS Basi di dati Lezione 4 ARGOMENTI Lezione 4 Filtrare i dati Esempio 1 Query Cos è Creare Query in visualizza struttura Criteri di ricerca Esempio 2 Esempio 3 Esempio 4 Creare Query in creazione

Dettagli

Corso di Informatica Generale (C. L. Economia e Commercio) Ing. Valerio Lacagnina Rappresentazione in virgola mobile

Corso di Informatica Generale (C. L. Economia e Commercio) Ing. Valerio Lacagnina Rappresentazione in virgola mobile Problemi connessi all utilizzo di un numero di bit limitato Abbiamo visto quali sono i vantaggi dell utilizzo della rappresentazione in complemento alla base: corrispondenza biunivoca fra rappresentazione

Dettagli

La selezione binaria

La selezione binaria Andrea Marin Università Ca Foscari Venezia Laurea in Informatica Corso di Programmazione part-time a.a. 2011/2012 Introduzione L esecuzione di tutte le istruzioni in sequenza può non è sufficiente per

Dettagli

Uso di base delle funzioni in Microsoft Excel

Uso di base delle funzioni in Microsoft Excel Uso di base delle funzioni in Microsoft Excel Le funzioni Una funzione è un operatore che applicato a uno o più argomenti (valori, siano essi numeri con virgola, numeri interi, stringhe di caratteri) restituisce

Dettagli

16.3.1 Alberi binari di ricerca

16.3.1 Alberi binari di ricerca 442 CAPITOLO 16. STRUTTURE DI DATI DINAMICHE root 7 5 11 2 8 13 10 Figura 16.11 Esempio di albero binario: ogni nodo contiene il dato da immagazzinare e tre puntatori che definiscono le sue relazioni di

Dettagli

Università di Torino Facoltà di Scienze MFN Corso di Studi in Informatica. Programmazione I - corso B a.a. 2009-10. prof.

Università di Torino Facoltà di Scienze MFN Corso di Studi in Informatica. Programmazione I - corso B a.a. 2009-10. prof. Università di Torino Facoltà di Scienze MFN Corso di Studi in Informatica Programmazione I - corso B a.a. 009-10 prof. Viviana Bono Blocco 9 Metodi statici: passaggio parametri, variabili locali, record

Dettagli

3 CENNI DI TEORIA DELLA COMPLESSITA COMPUTAZIONALE. E. Amaldi Fondamenti di R.O. Politecnico di Milano 1

3 CENNI DI TEORIA DELLA COMPLESSITA COMPUTAZIONALE. E. Amaldi Fondamenti di R.O. Politecnico di Milano 1 3 CENNI DI TEORIA DELLA COMPLESSITA COMPUTAZIONALE E. Amaldi Fondamenti di R.O. Politecnico di Milano 1 Scopo: Stimare l onere computazionale per risolvere problemi di ottimizzazione e di altra natura

Dettagli