Gestione dei file. Gestione dei file. Gestione dei file. Gestione dei file Costruiamo un oggetto di tipo FileReader: Gestione dei file

Dimensione: px
Iniziare la visualizzazioe della pagina:

Download "Gestione dei file. Gestione dei file. Gestione dei file. Gestione dei file Costruiamo un oggetto di tipo FileReader: Gestione dei file"

Transcript

1 Finora abbiamo visto programmi che utilizzano solo flussi di ingresso standard e questi flussi erano collegati attraverso la ridirezione ai corrispondenti file fisici. Vogliamo definire un file di lettura o di scrittura nel programma per poter leggere più di un file e poter gestire file diversi da System.in e System.out. Utilizzeremo le classi FileReader e FileWriter del pacchetto java.io. Per poter leggere caratteri da un file, esistente, occorre aprire il file in lettura; questa operazione si traduce in Java nella creazione di un oggetto di tipo FileReader. (par. 11.1) Il costruttore accetta il nome del file sotto forma di stringa. Se il file non esiste viene lanciata l eccezione FileNotFoundException. Supponiamo di leggere i dati da un file fisico di nome ingresso.txt. Costruiamo un oggetto di tipo FileReader: FileReader fl = new FileReader("ingresso.txt"); Con un oggetto di tipo FileReader si può invocare il metodo read, che legge un singolo carattere e lo restituisce sottoforma di intero compreso nell intervallo [0, 65535], iniziando dal primo carattere del file e procedendo fino alla fine del file stesso; se il file è finito il metodo read restituisce un intero che vale -1. Per facilitare l acquisizione dei dati si può usare un oggetto di tipo Scanner o di tipo BufferedReader: Scanner in = new Scanner(fl); e poi leggere con i metodi della classe Scanner, come in.nextint, oppure BufferedReader in = new BuffredReader(fl); e leggere con readline e poi utilizzare i metodi per la conversione ai vari tipi di dato. Al termine della lettura si deve chiudere il file: in.close(); Se il file non viene chiuso non viene segnalato alcun errore, ma è meglio eseguire la chiusura da programma. L eccezione FileNotFoundException è a controllo obbligatorio e quindi, se non è gestita, nell intestazione del metodo che apre il file si deve inserire: throws FileNotFoundException 1

2 Per poter scrivere dei caratteri in un file, occorre aprire il file in scrittura; questa operazione si traduce in Java nella creazione di un oggetto di tipo FileWriter: FileWriter fs = new FileWriter("uscita.txt"); Il costruttore accetta il nome del file sotto forma di stringa. Per poter usare i metodi print e println, si deve costruire PrintWriter: un oggetto di tipo PrintWriter out = new PrintWriter(fs); Il costruttore di PrintWriter accetta anche una stringa con il nome del file per cui si può più semplicemente scrivere: PrintWriter out = new PrintWriter("uscita.txt"); Se il file non esiste, esso viene creato: viene costruito un file fisico con il nome indicato nella stringa ed in maniera sequenziale vengono inseriti i dati corrispondenti alle istruzioni del metodo print. Se il file esiste già, esso viene cancellato e poi costruito nuovamente, vale a dire sovrascritto: la testina di scrittura si riposiziona all inizio del file per inserire i nuovi dati. È necessario chiudere il file: out.close(); non viene segnalato alcun errore ma può succedere che il programma termini prima che i dati siano stati inseriti e pertanto il contenuto del file rimane incompleto. Se è presente l istruzione close il file deve essere chiuso prima della terminazione del programma, e il file viene chiuso solo se i dati sono stati tutti scritti nel file. La classe Scanner è stata progettata per rendere più comoda la lettura dei dati e pertanto è stato scelto di non legarla ad eccezioni di tipo controllato. Il metodo readline della classe BufferedReader invece solleva una eccezione controllata (IOException), che pertanto deve essere indicata con la clausola throws. Le classi che gestiscono i file possono sollevare eccezioni che riguardano lo scambio di informazioni con l esterno. Dal momento che FileNotFoundException è una sottoclasse di IOException, se un metodo dovesse dichiararle entrambe, può dichiarare solo quelle superiore, vale a dire basta che indichi: throws IOException 2

3 Poiché anche i metodi di lettura possono sollevare analoghe eccezioni, quando si usano i file non standard, è sempre conveniente scrivere la clausola throws IOException nell intestazione del main (che comporta anche l uso di eccezioni di eventuali sottoclassi). Si può gestire l acquisizione dei nomi dei file tramite l utilizzo degli argomenti sulla riga di comando; in tale modo è possibile inserire un controllo almeno sul fatto di aver scritto il numero esatto dei file da gestire; se, invece, i nomi sono errati, e quindi il file non esiste, si solleva l eccezione (che eventualmente può essere catturata). Il parametro String arg[] viene ad avere per componenti i nomi dei file che si vogliono utilizzare. /**Utilizzo di file lettore e scrittore */ import java.io.filereader; import java.io.filewriter; import java.io.bufferedreader; import java.io.printwriter; import java.io.ioexception; /* Si ricopia il contenuto di un file di testo una riga alla volta in un altro file; i nomi dei due file sono passati come parametri dalla riga di comando */ public class ProvaFile{ public static void main (String[] arg) throws IOException{ //inizio main if (arg.length < 2) System.out.println("dare i nomi" + "dei due file sulla riga " + " di comando\n"); else {//aprire i file BufferedReader in = new BufferedReader (new FileReader(arg[0])); PrintWriter out = new PrintWriter (new FileWriter(arg[1])); /* acquisire dal file "in" una riga e scrivere nel file "out" la stessa riga */ String line = in.readline(); while (line!= null){ out.println(line); line = in.readline(); }//fine while 3

4 //chiusura dei due file out.close(); //file di scrittura in.close(); // file di lettura }//fine else }//fine main }//fine classe Ordinamento per inserimento Dopo aver compilato e costruito il file da ricopiare dare il comando: java Provafile ingresso.txt uscita.txt Ordinamento per inserimento L idea è quella di inserire una componente in ordine rispetto ad una sequenza di componenti già ordinate. Esempio. Vogliamo inserire 6 nella sequenza: La cosa più efficiente è partire dall ultima posizione e slittare verso destra le componenti che sono maggiori si 6: in tale modo quelle più piccole restano ferme : ora c è posto per inserire 6. Ordinamento per inserimento Per effettuare l ordinamento si parte dalla seconda componente (la prima è ordinata rispetto alle precedenti ) e la si inserisce in ordine rispetto alla prima, poi si considera la terza, e la si inserisce in ordine rispetto alle prime due, in generale: si vuole inserire la k-esima componente in ordine rispetto alle k-1 già ordinate. Ordinamento per inserimento Poiché il numero di componenti non aumenta, per poter slittare verso destra le componenti che precedono nella sequenza, è necessaria una variabile di appoggio x per salvare il valore: x Ordinamento per inserimento Bisogna non uscire dall array se si deve inserire un valore prima della prima componente. Ci sono varie strategie per realizzare ciò, una di queste è sfruttare la valutazione pigra dei predicati : for(k=1; k<=n-1; k++) {//si inizia // dalla seconda x=v[k]; //inserire v[k] i=k; while((i!=0) && (x < v[i-1])){ v[i]=v[i-1]; i--; } //fine while v[i]=x; }//fine for 4

5 Ordinamento per inserimento Complessità. Caso favorevole. l array è già ordinato il predicato del ciclo interno (while) è sempre falso, ( x < v[i-1] è falso), quindi il numero di operazioni è proporzionale a n: si ha Ω (n). Ordinamento per inserimento Caso peggiore. L array è in ordine inverso il ciclo interno (while) viene sempre eseguito per valori crescenti di i = k (k=1, 2,, n-1): (n-1) = n (n-1)/2 quindi O(n 2 /2) Algoritmi esponenziali Algoritmi esponenziali Supponiamo che f(n) sia la funzione che rappresenta il numero di operazioni eseguite da un algoritmo e supponiamo che il tempo necessario per compiere una operazione sia un microsecondo: 1µs = 10-6 sec. Vogliamo vedere che per valori di n non elevati gli algoritmi impiegano un tempo troppo elevato per poter essere utilizzati: gli algoritmi esponenziali sono impraticabili. Algoritmi esponenziali Vediamo questa tabella dove riportiamo, al variare di n, il tempo impiegato da alcune funzioni di n n log 2 (n) 100*n 10*n 2 n 3 2 n µs 1ms 1ms 1ms 1024µs ~ 1ms µs 2ms 4ms 8ms 1.048sec µs 6ms 36ms 0.21sec 2 60 µs ~ 366 secoli Algoritmi esponenziali 2 60 µs ~ 366 secoli, vediamo come mai 2 60 µs ~ µs ~ µs~ sec ( ) (1µs = 10-6 sec ) Quanti secondi in un anno? 1 minuto = 60 secondi 1 ora = 3600 secondi 1 giorno = secondi 1 secolo = secondi secondi secoli = = = 366 secondi in un secolo

6 Algoritmi esponenziali Esistono degli algoritmi che sono intrinsecamente esponenziali: calcolare le permutazioni di n elementi: n! ~ n n Ci sono problemi che sono risolti da un algoritmo deterministico esponenziale, ma il cui algoritmo non deterministico è polinomiale. Algoritmi esponenziali L algoritmo non deterministico è un algoritmo ideale che può essere simulato pensando di poter eseguire scelte contemporanee. Esso è rappresentabile su un albero: la profondità dell albero può essere proporzionale alla dimensione del problema. Tali problemi si chiamano problemi NP (Non deterministico Polinomiale). Algoritmi esponenziali Esempio. Consideriamo la formula logica F(x 1, x 2, x 3 ) = (x 1 e x 2 e x 3 ) o (non x 1 e non x 2 ) e ci chiediamo se esiste una scelta di valori per le variabili x 1, x 2, x 3 che renda vera F. Un algoritmo deterministico prova tutte le possibilità e poiché il valore di x i può essere vero o falso, le possibilità sono 2 3. Algoritmi esponenziali In generale considerando F(x 1, x 2,.., x n ) il problema può essere risolto in un tempo O(2 n ). L algoritmo non deterministico è in grado di scegliere il valore di x i che porta alla soluzione. Per simulare tale comportamento si può costruire un albero: ogni nodo rappresenta una variabile della formula; da ogni nodo partono due rami che rappresentano il vero e il falso. Algoritmi esponenziali Se potessimo esplorare l albero in modo da poter percorrere contemporaneamente i due rami V e F, in n passi arriveremmo alle foglie. Quindi l algoritmo non deterministico è O(n). Complessità asintotica Le considerazioni fatte sulla complessità valgono solo se n e F(n) x 1 x 2 x 3 v x 1 x 2 x 2 x 3 x 3 x 3 x f Se invece n si mantiene limitato anche un algoritmo esponenziale può essere utilizzato; per lo stesso motivo anche la costante moltiplicativa, che solitamente trascuriamo nella notazione O-grande, può invece essere fondamentale nella scelta. 6

7 Complessità asintotica Esempio. f 1 (n) = 1000 * n f 2 (n) = 10 * n 2 f 1 è O(n) f 2 è O(n 2 ) Quindi: se n è preferibile f 1 se n 10 è preferibile f 2, infatti: 1000 * n 1000*10 = * n 2 10*100 = 10 3 Due esempi di analisi asintotica Problema. Dati n numeri, costruire una sequenza di numeri che rappresentino le medie dei precedenti. Analisi. Data la sequenza x 0, x 1,, x n-1 costruire la sequenza a 0, a 1,, a n-1 in modo tale che a i = Σ x k / (i+1) k=0,1,, i Questo è un problema che si incontra spesso in economia: dati i profitti annuali, osservare i profitti medi degli ultimi 2, 3,, 5 anni. Due esempi di analisi asintotica Primo algoritmo. // definizione dati // acquisizione e stampa di n e x per i da 0 a n-1 eseguire s=0 per k da 0 a i eseguire s = s + x[k] //fine per a[i] = s/(i+1) //fine per Due esempi di analisi asintotica Ci sono due strutture iterative, delle quali quella più interna varia con i e le operazioni del ciclo interno sono eseguite: n = n(n+1)/2 Le operazioni del ciclo esterno sono c n. Quindi la complessità è O(n 2 ). Due esempi di analisi asintotica Secondo algoritmo. La media a i è simile alla successiva a i+1 : a i = Σ x k / (i+1) k = 0,1,, i a i+1 = Σ x k / ((i+1)+1) k = 0,1,, i, i+1 dove le somme al numeratore sono s i = x 0 + x x i s i+1 = x 0 + x x i + x i+1 = s i + x i+1 Due esempi di analisi asintotica Ottimizzando il calcolo della media: Secondo algoritmo. s=0 per i da 0 a n-1 eseguire s = s + x[i] a[i] = s/(i+1) //fine per La complessità di questo algoritmo è O(n). 7

8 Una scomposizione di un problema P in sottoproblemi P 1, P 2,, P n si dice ricorsiva se almeno uno dei sottoproblemi è formalmente simile a P e di dimensione inferiore. Esempio. Fattoriale di un numero naturale. Per definizione 0! = 1 (caso base) n! = n*(n-1)! Vediamo che n! viene definito tramite (n-1)! che è un numero più piccolo di n. (Capitolo 12) Per capire una definizione ricorsiva, bisogna espanderla : si ricopia la formula sostituendo al posto di n il numero n-1 e si prosegue fino al caso base : n! = n*(n-1)! = n* [(n-1) * (n-2)!] =... = = n*(n-1)*... * (n-n)! Poiché (n-n)! = 0! = 1 per definizione, si ottiene: n! = n*(n-1)*... * 1 Ci chiediamo se è una buona definizione. È una buona definizione perché esiste una dimensione del problema, una condizione, che non necessita di ulteriori scomposizioni; il problema viene risolto direttamente: 0! = 1 Il problema per n=0 è risolto senza utilizzo della ricorsione. Possiamo scrivere algoritmi ricorsivi, algoritmi che richiamano se stessi. Il main non può essere ricorsivo: il main è richiamato dal Sistema Operativo. Un generico algoritmo ricorsivo avrà una struttura del tipo: se condizione allora risolvi direttamente altrimenti ricorsione oppure se condizione allora ricorsione In questo caso può esserci o meno una alternativa: se la condizione è falsa non si esegue nulla. Se la ricorsione non termina, si hanno infinite chiamate per l algoritmo e si può occupare tutta la memoria: questo è un errore grave, come quello di costruire un ciclo infinito. 8

9 La scrittura di un algoritmo ricorsivo è semplice se si sta realizzando una formula matematica come quella del fattoriale: 0! =1, n! = n*(n-1)! intestazione del metodo fattoriale(n intero) definizione variabili f intero se n==0 allora f 1 altrimenti f n * fattoriale(n-1) //finese restituire f Il metodo ricorsivo avrà una scrittura del tipo: public static int fattoriale(int n){ int f; if(n == 0) f = 1; else f = n * fattoriale(n-1); return f; }//fine fattoriale ricorsivo Cosa accade veramente? Facciamo uno schema della scomposizione: n* n! (n-1)* (n-1)! (n-2)! I vari prodotti n*, (n-1)*,, 1* restano sospesi perché il controllo passa al metodo chiamato. Dopo l ultima chiamata che restituisce 1, tale valore torna indietro al chiamante e viene eseguito l ultimo prodotto sospeso (1* ); tale valore viene a sua volta restituito al chiamante, viene eseguito il prodotto sospeso 2*, 1* 0! =1 Come può un metodo rimanere sospeso e poi, quando si riattiva, eseguire i prodotti giusti? Nel codice del metodo appaiono due valori per la variabile n: appare n nell intestazione: public static int fattoriale(int n) appare n nel prodotto e n-1 nella chiamata: f = n * fattoriale(n-1); Abbiamo visto che quando un metodo viene invocato il controllo passa dal chiamante al metodo chiamato e l ambiente di quest ultimo è quello attivo durante l esecuzione del metodo (RuntimeStack). Se anche nel metodo chiamato c è una invocazione ad un altro metodo, il primo rimane sospeso e il controllo passa al secondo, e così via. Ogni metodo che termina restituisce il controllo al suo chiamante. 9

10 Nel caso della ricorsione il metodo è sempre lo stesso: nelle varie copie del metodo sono memorizzati i parametri e le istruzioni di quella chiamata: f f f ritorno chiama f. chiama f. main chiama f.. ogni ambiente ha la sua copia di parametri e di variabili locali Che cosa deve essere memorizzato per poter eseguire le operazioni? Si deve memorizzare: quali sono le operazioni da eseguire prima e dopo la chiamata quale è il valore delle variabili a quel livello di chiamata. Quando un metodo termina, l area allocata ritorna libera. Vediamo un esempio di questa memorizzazione calcolando ricorsivamente 5! 1 * 0! 2 * 1! 3 * 2! 4 * 3! 5 * 4! ritorno 1 2*1 = 2 3*2 = 6 4*6 = 24 5*24 =120 Complessità di un algoritmo ricorsivo Il tempo di un algoritmo ricorsivo si ottiene sommando vari tempi: il tempo delle operazioni eseguite nell algoritmo (esclusa la ricorsione) il tempo per la chiamata di un metodo (ricorsivo o no) il tempo dell algoritmo (ricorsivo) di dimensione inferiore (tempo per tutte le chiamate successive) Il tempo delle operazioni della parte non ricorsiva si calcola contando confronti, assegnazioni, cicli: T(n). Complessità di un algoritmo ricorsivo Il tempo per effettuare una singola chiamata di metodo è O(1): infatti si effettua un passaggio di parametri, in chiamata, e il ritorno di un valore, quando il metodo è terminato; questo equivale ad un numero finito di assegnazioni e pertanto è costante. Il tempo dell algoritmo di dimensione inferiore è T(dimensioneinferiore) e rappresenta il costo puro della ricorsione: rappresenta il numero delle chiamate ricorsive. Complessità di un algoritmo ricorsivo Esempio. Complessità dell algoritmo ricorsivo per il calcolo di n! Sia T(n) il tempo per calcolare n!: possiamo anche contare solo il numero di moltiplicazioni, dal momento che questa è l operazione fondamentale: costante se n=0 T(n) = costante + T(n-1) se n>0 Se contiamo solo le moltiplicazioni la prima costante è 0 e la seconda costante è 1. 10

11 Complessità di un algoritmo ricorsivo Se invece vogliamo contare tutte le operazioni avremo: per la prima costante t c + t a + t ritorno ~ c per la seconda costante: t c + t prodotto + t chiamata + t a + t ritorno ~ c Otteniamo così la formula: T(n) = c + T(n-1) Complessità di un algoritmo ricorsivo Analogamente a quanto fatto con la definizione, espandiamo la formula: T(n) = c + T(n-1) = c + (c + T(n-2)) = 2c + T(n-2) = = 2c + (c + T(n-3)) = 3c + T(n-3) = = 3c + (c + T(n-4)) = 4c + T(n-4) =. = n c + T(n-n) = n c + T(0) = = (n+1) c O(n) Se avessimo contato solo le moltiplicazioni, avremmo avuto: T(n) = 1 + T(n-1) =. = n + T(0) = n e iterazione Avremmo anche potuto calcolare il fattoriale in maniera iterativa; la scomposizione iterativa del fattoriale è diversa: f f*1 f f*2 n! f f*n e iterazione Anche la scrittura dell algoritmo cambia; possiamo scrivere delle istruzioni del tipo: intestazione del metodo fattiterativo(n intero) definizione variabili f, i intero f 1 per i da 1 a n eseguire f f * i //fineper restituire f e iterazione La complessità non cambia: abbiamo infatti una struttura iterativa che viene eseguita n volte: t a + (n+1) t p + n t a + t ritorno quindi sempre c n operazioni. Quando in un metodo ricorsivo c è una sola chiamata a se stesso la ricorsione si dice diretta; se invece il metodo chiama un altro metodo che ne chiama un altro ancora (e anche vari altri) e quest ultimo chiama il primo, la ricorsione si dice indiretta. Si parla poi di ricorsione lineare se la chiamata è unica nel metodo (diretta o indiretta); si parla di ricorsione multipla se c è più di una chiamata (binaria se le chiamate sono due). Nel fattoriale la ricorsione è diretta e lineare. 11

12 Leonardo da Pisa (detto Fibonacci, ) fu un illustre matematico che si interessò di vari problemi, alcuni dei quali oggi potremmo chiamarli dinamica delle popolazioni, ossia lo studio di come si evolvono le popolazioni. Problema astratto. Consideriamo: un isola deserta: sistema isolato una coppia di conigli genera un altra coppia ogni anno i conigli si riproducono solo dopo due anni dalla loro nascita i conigli sono immortali (n + ) Quante coppie ci sono dopo n anni? (par. 12.4) Indichiamo con F n il numero di conigli dopo n anni e proviamo a calcolarli a partire dal primo anno: F 1 = 1 coppia iniziale F 2 = 1 la stessa coppia F 3 = = 2 F 1 + la coppia nata da F 1 ( 2 anni) F 4 = = 3 F 3 + la coppia nata da F 2 ( 2 anni) F 5 = = 5 F 4 + le due coppie nate da F 3 ( 2 anni).. In generale si avrà F n = F n-1 + F n-2 dove F n-1 rappresenta le coppie presenti l anno precedente ed F n-2 rappresenta una nuova coppia per ogni coppia di almeno 2 anni. I numeri si calcolano facilmente sommando i valori dei due posti precedenti: n F(n) L algoritmo più immediato da scrivere è quello che ricopia la definizione e pertanto è un algoritmo ricorsivo. Il caso base è rappresentato da F 1 = 1 e F 2 = 1 L algoritmo avrà una scrittura del tipo: intestazione metodo fibonacci (n intero) definizione variabili fib intero se n ==1 oppure n ==2 allora fib 1 //caso base altrimenti fib fibonacci (n-1) + fibonacci (n-2) //finese restituire fib //fine metodo Possiamo rappresentare le chiamate ricorsive con una struttura di albero, come abbiamo fatto con il fattoriale. Un albero è un insieme di punti, detti nodi, a cui è associata una struttura d ordine che gode delle seguenti proprietà: esiste uno ed un solo nodo che precede tutti gli altri, detto radice ogni nodo, esclusa la radice, ha un unico predecessore immediato. 12

13 Ogni nodo con successore si chiama padre. Ogni nodo con predecessore si chiama figlio. I nodi senza successore si chiamano foglie. L arco che collega un nodo padre a un nodo figlio si chiama ramo. Possiamo rappresentare l albero per n = 5. F 5 F 4 F 3 F 3 F 2 F 2 F 1 F 2 F 1 F 5 è la radice, F 1 e F 2 sono foglie; le foglie non hanno ulteriori chiamate ricorsive e restituiscono il valore 1 e nel ritorno si eseguono le somme. Si può dimostrare che il numero delle foglie dell albero della ricorsione per la costruzione di F n coincide con il valore di F n. Se vogliamo contare le chiamate del metodo, dobbiamo anche aggiungere il numero dei nodi interni, che corrisponde al numero delle chiamate ricorsive. Si può dimostrare che tale numero è uguale al numero delle foglie meno uno F n -1. Possiamo concludere che: la complessità dell algoritmo ricorsivo cresce come F n. Osservando l albero della ricorsione si nota che molti valori F n sono calcolati più volte: nel caso di F 5, F 2 viene calcolato 3 volte. Si possono pertanto memorizzare tali valori in un array e calcolarli una volta sola. Si dovrà però dare una dimensione all array, stabilendo un numero massimo di elementi da calcolare. intestazione metodo fibonacci2 (n intero) definizione variabili fib[nummax], i intero fib[1] 1 fib[2] 1 per //fineper restituire fib[n] //fine metodo i da 3 a n eseguire fib[i] fib[i-1] + fib[i-2] Quale complessità ha l algoritmo che utilizza l array? tempo O(n): ciclo che viene eseguito n volte spazio O(n): si utilizza un array di nummax componenti per calcolare F n con n<=nummax Si può scrivere un algoritmo ancora più efficiente. 13

14 Osserviamo nuovamente il calcolo dei valori F n, ed osserviamo che ad ogni passo si utilizzano solo i valori precedenti, che possono essere salvati in due variabili scalari: F 1 = 1 F 2 = 1 F 3 = F 2 + F 1 F 4 = F 3 + F 2 F 5 = F 4 + F 3 queste somme sono del tipo: f f + valoreprecedente Si ottiene così il seguente algoritmo: intestazione metodo fibonacci3 (n intero) definizione variabili fib, i, prec, prec1 intero prec 1 //F1 fib 1 //F2 per i da 3 a n eseguire prec1 fib //salviamo F 2, prima di fib fib + prec // F 3 = F 2 + F 1 prec prec1 // perché servirà nel //fineper //calcolo di F 4 restituire fib //fine metodo Quale complessità ha l algoritmo che utilizza le sole variabili scalari? tempo spazio O(n): ciclo che viene eseguito n volte O(1): si utilizza un numero costante di locazioni di memoria Per calcolare la complessità dell algoritmo ricorsivo dobbiamo capire come il valore di F n cresce, andando all infinito. Possiamo stimare il valore utilizzando un algoritmo numerico. Si cerca una funzione che soddisfi la relazione di ricorrenza F n = F n-1 + F n-2 e si prova con a n, a 0; l equazione diventa: a n = a n-1 + a n-2 da cui raccogliendo a n-2 si ottiene: a n-2 ( a 2 a 1) = 0 Poiché a 0 cerchiamo le soluzioni dell equazione ( a 2 a 1) = 0 e troviamo le due radici reali: φ = (1 + 5 ) / 2 ~ φ = (1-5 ) / 2 ~ φ è la sezione aurea. Si può dimostrare che F n = (φ n -φ n ) / 5 Esiste quindi un algoritmo numerico con il quale calcolare il numero F n. Però tale algoritmo non può essere preciso, dal momento che F n è un numero naturale e la radice di 5 è un numero irrazionale: quindi una applicazione di tale algoritmo fornisce, per molti valori di n, solo una approssimazione. La complessità di tempo e di spazio è O(1). 14

15 Utilizziamo la formula F n = (φ n -φ n ) / 5 per stimare come F(n) + L algoritmo ricorsivo ha complessità O(F n ); dal momento che: φ < 1 si ha che φ n 0 1< φ < 2 si ha che φ n < 2 n e pertanto l algoritmo cresce in maniera esponenziale con limitazione superiore 2 n : tempo O(2 n ). F 5 F 4 F 3 F 3 F 2 F 2 F 1 F 2 F 1 La complessità di spazio è O(n); infatti le chiamate ricorsive si espandono in profondità, non sono contemporanee: F 5, F 4, F 3, F 2, ritorno, F 1, ritorno F 2, calcola F 3, ritorno, La torre di Hanoi La leggenda narra che dei sacerdoti di un tempio di Brahma lavorino per spostare una pila di 64 dischi d oro da un piolo ad un altro, utilizzandone uno di appoggio e seguendo delle regole; alla fine del lavoro ci sarà la fine del mondo La torre di Hanoi La configurazione finale dovrà essere: A B C A B C La torre di Hanoi La regola è la seguente: si può spostare un solo disco alla volta non si può mettere un disco grande su uno piccolo. La soluzione più intuitiva è quella ricorsiva: se spostiamo la pila di n-1 dischi da A a B, possiamo muovere il primo disco da A a C e poi spostare la pila di n-1 dischi da B a C. Indichiamo con H(n, A, B,C) il problema di Hanoi di dimensione n. (Esercizio P12.13) La torre di Hanoi La scomposizione ricorsiva sarà perciò: H(n-1, A, C, B) H(1, A, B, C) //muove un disco H(n-1, B, A, C) Possiamo scrivere le chiamate ricorsive nel caso n=3. Applichiamo l espansione della formula ricorsiva e vediamo come si muovono i dischi. 15

16 La torre di Hanoi La torre di Hanoi H(3,A,B,C) H(2,A,C,B) H(1,A,B,C) H(2,B,A,C) H(1,A,B,C) H(1,A,C,B) H(1,C,A,B) H(1,B,C,A) H(1,B,A,C) H(1,A,B,C) Complessità. Quanti sono gli spostamenti dei dischi? Per spostare un disco da un piolo ad un altro, ed ottenere la stessa configurazione, si deve spostare 2 volte la pila di dischi che gli sta sopra; quindi ogni disco si muove un numero di volte che è doppio rispetto al disco che gli sta immediatamente sotto. Contiamo gli spostamenti a partire dal primo: La torre di Hanoi disco 1 1 spostamento *2 = 4 = *4 = 8 = *8 = 16 = 2 4 n 2 n-1 sommiamo gli spostamenti n-1 = 2 n -1 quindi O(2 n ) l algoritmo è esponenziale La torre di Hanoi Si può anche scrivere un algoritmo iterativo, che rimane esponenziale, osservando il movimento dei dischi: disco1 A C disco2 A B C disco3 A C B A C I dischi pari percorrono ciclicamente in ordine alfabetico i pioli, i dischi dispari li percorrono in ordine inverso. Divide et impera Divide et impera La tecnica detta divide et impera è una strategia generale per impostare algoritmi. Consideriamo un problema P e sia n la dimensione dei dati, la strategia consiste nel: suddividere il problema in k sottoproblemi P i di dimensione inferiore (ciascuno di dimensione n i ) e successivamente riunire i risultati ottenuti dalle k soluzioni. Frase attribuita a Filippo il Macedone; fu un principio politico: mantenere divise le popolazioni dominate per poter governare con più facilità. (Argomenti avanzati 13.3) 16

17 Divide et impera Se i k sottoproblemi sono formalmente simili al problema di partenza, si ottiene una scomposizione ricorsiva. Ci deve pertanto essere una dimensione h del problema che porti ad una risoluzione diretta, vale a dire che non necessiti della ricorsione. Indichiamo con: S l insieme dei dati k il numero dei sottoproblemi h la dimensione limite Divide et impera: schema generale algoritmo DIVETIMP (S, n) se n < h allora risolvere direttamente il problema P altrimenti dividere S in k sottoinsiemi risolvere separatamente i k sottoproblemi P 1,, P k : DIVETIMP(S 1,n 1 ),, DIVETIMP(S k,n k ) riunire i risultati ottenuti //finese //fine algoritmo Divide et impera: complessità Indichiamo con T(n) la complessità del problema P sull insieme dei dati di dimensione n; poiché l algoritmo è ricorsivo si ottengono delle formule di ricorrenza. Indichiamo con: D(n): complessità dell algoritmo per dividere l insieme C(n): complessità dell algoritmo per riunire i risultati T(n i ): complessità dell algoritmo sull insieme di dimensione n i. Divide et impera: complessità La formula di ricorrenza è la seguente: T(n) = costante n<h T(n) = D(n) + C(n) + T(n 1 ) + T(n 2 ) + + T(n k ) Queste formule si espandono in modo analogo a quanto visto per il fattoriale ricorsivo. Analisi. L idea è la seguente: è più conveniente ordinare due array di s e t componenti piuttosto che un array di n componenti (s + t = n) si aumenta l efficienza dell ordinamento scambiando elementi lontani tra loro. (Argomenti avanzati 13.3) 17

18 Verifichiamo la prima idea. Supponiamo s=t=n/2 e prendiamo la formula n(n-1)/2 che rappresenta la complessità dell ordinamento nel caso peggiore e riscriviamola per n/2 invece che n: 2 [(n/2) (n/2 1) /2] = n 2 /4 n/2 n 2 /4 n/2 < n 2 /2 n/2 = (n 2 n)/2 = = n (n-1) /2 Verifichiamo la seconda idea. Supponiamo di avere un array ordinato in senso inverso; scambiando gli elementi opposti (il primo con l ultimo, il secondo con il penultimo, ecc.) in n/2 operazioni ordiniamo l array. Questi elementi sono lontani tra loro: quelli più grandi sono al posto di quelli più piccoli. Dividiamo l insieme in due parti (prima idea) e sfruttiamo la seconda idea: scambiare elementi lontani. Scegliamo un elemento dell array per eseguire i confronti e lo chiamiamo conf; dividiamo l insieme in modo tale che gli elementi più piccoli di conf possano essere messi a sinistra di conf e quelli più grandi a destra, rispettando così l ordine. A questo punto l insieme è diviso in due parti indipendenti e l elemento conf è al suo posto. conf Si potrà proseguire ordinando separatamente le due parti di array. Possiamo farlo in maniera ricorsiva. Si prosegue fino a considerare un array di dimensione 1 (dimensione limite), che non dovrà essere ulteriormente suddiviso. Se guardiamo l array dalla prima componente all ultima, vediamo che l array è ordinato: guardare tutto l array corrisponde a riunire i risultati. Scriviamo il progetto dell algoritmo secondo lo schema divide et impera. Poiché l array iniziale viene considerato in parti più piccole, sulle quali applicare lo stesso metodo, progettiamo l ordinamento di un array v dalla componente n1 alla componente n2. Alla prima invocazione del metodo n1 ed n2 saranno rispettivamente la prima e l ultima componente. algoritmo quicksort(n1, n2, v) se n1 < n2 allora //finese //fine quicksort chiamare l algoritmo partizione(n1, n2, v) che restituisce il valore k della posizione di conf chiamare quicksort(n1, k-1, v) chiamare quicksort(k+1, n2, v) Quando n1=n2 l array ha un solo elemento e pertanto la ricorsione ha termine. 18

19 Come scegliere l elemento conf? Dobbiamo stabilire un criterio che si possa facilmente ripetere in tutte le suddivisioni successive. Stabiliamo di scegliere la prima componente di quella porzione di array (da n1 a n2) che vogliamo ordinare: v[n1]. Ci sono varie scritture dell algoritmo quicksort, ma lasciano inalterata la complessità. Per realizzare la partizione avremo bisogno due indici: un indice i che scorre l array con valori crescenti e che parte dalla posizione successiva a quella di conf (i=n1+1), un altro indice k che descrive l array con valori decrescenti e parte dall ultima posizione (k=n2). Quando questi due indici saranno uguali avremo terminato la partizione e si potrà sistemare conf al suo posto. Vediamo un progetto per l algoritmo di partizione. algoritmo partizione(n1, n2, v) conf v[n1] i n1+1 k n2 mentre i k eseguire mentre v[i] conf e i k eseguire i i+1 //fine mentre mentre v[k] conf e i k eseguire k k-1 //fine mentre scambiare v[i] con v[k] //elementi lontani //fine mentre: ciclo esterno //sistemare conf nella posizione k=i //è al suo posto se v[k] > conf allora k k-1 //finese scambiare v[n1] con v[k] //fine partizione E necessario il confronto tra conf e v[k]? Esempio conf i=2 i=3 k=6 k= i=4 i=5 k=5 i = k = 5 termina anche il ciclo esterno v[k]>conf conf =10<13= v[k] quindi k Esempio conf i=2 i=3 i=4 i=5 i=6 i=7= k i = k = 7 termina anche il ciclo esterno v[k]>conf falso : k non varia

20 Complessità. Contiamo i confronti tra conf e gli elementi v[i]: 0 se n = 0,1 (n1<n2) T(n) = D(n) + C(n) + T(k-1) + T(n-k) D(n) = complessità dell algoritmo partizione C(n) = 0 guardare le due parti dell array D(n) è O(n): n-1 confronti nei predicati dei cicli interni + 1 confronto per sistemare conf. Caso peggiore: vettore ordinato, la partizione è sbilanciata: T(n) = n + T(0) + T(n-1) = n + T(n-1) = = n + (n-1 + T(0) + T(n-2)) = n + n-1 + T(n-2) = = n + (n-1) + (n-2) + T(n-3) = =.. = n + (n-1) T(0) + T(n (n-1)) = = n (n-1)/2 O(n 2 /2) Caso favorevole: conf sempre al centro, la partizione è bilanciata L algoritmo del libro è scritto diversamente: from = n1 to = n2 T(n) = n + T(n/2) + T(n/2) = n + 2T(n/2) = = n + 2(n/2 + 2T(n/4)) = 2n T(n/2 2 ) = =.. = k n + 2 k T(n/2 k ) Se n = 2 k allora k = log 2 n O(n log 2 n) i=n1-1 k=n2+1 (valori esterni), conf=pivot il ciclo esterno ha predicato i<k ; all inizio del ciclo i++ ; il confronto v[i]<conf è falso (sono uguali) quindi si passa al secondo ciclo e conf viene messo come ultimo (non necessariamente al suo posto). Manca il confronto i k, perché in fondo c è conf. Nella versione con conf al centro è necessario il predicato i k per non uscire dall array (se conf è il più grande elemento, come nel secondo esempio). 20

Altri modi per leggere dati in ingresso

Altri modi per leggere dati in ingresso Errori Esiste anche un altra categoria di errori che si possono presentare durante l esecuzione e sono oggetti della classe Error. Può accadere che si occupi tutta la memoria disponibile; in questo caso

Dettagli

Divide et impera. Divide et impera. Divide et impera. Divide et impera

Divide et impera. Divide et impera. Divide et impera. Divide et impera Divide et impera Divide et impera La tecnica detta divide et impera è una strategia generale per impostare algoritmi (par. 9.4). Consideriamo un problema P e sia n la dimensione dei dati, la strategia

Dettagli

Algoritmi esponenziali

Algoritmi esponenziali Algoritmi esponenziali Algoritmi esponenziali Supponiamo che f(n) sia la funzione che rappresenta il numero di operazioni eseguite da un algoritmo e supponiamo che il tempo necessario per compiere una

Dettagli

Variabili locali. Variabili parametro. Prototipo di funzione. Prototipo di funzione. Moduli esterni. Moduli esterni

Variabili locali. Variabili parametro. Prototipo di funzione. Prototipo di funzione. Moduli esterni. Moduli esterni Variabili parametro Una variabile parametro di scambio nell intestazione della funzione: (char nome[], int n, double &a) è visibile all interno della funzione e non deve essere ridefinita viene inizializzata

Dettagli

Tempo e spazio di calcolo (continua)

Tempo e spazio di calcolo (continua) Tempo e spazio di calcolo (continua) I numeri di Fibonacci come case study (applichiamo ad un esempio completo le tecniche illustrate nei lucidi precedenti) Abbiamo introdotto tecniche per la correttezza

Dettagli

Tempo e spazio di calcolo (continua)

Tempo e spazio di calcolo (continua) Tempo e spazio di calcolo (continua) I numeri di Fibonacci come case study (applichiamo ad un esempio completo le tecniche illustrate nei lucidi precedenti) Abbiamo introdotto tecniche per la correttezza

Dettagli

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati Algoritmi e Strutture Dati Capitolo 1 Un introduzione informale agli algoritmi Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano Definizione informale di algoritmo Insieme di istruzioni, definite

Dettagli

Trasformare array paralleli in array di record

Trasformare array paralleli in array di record Trasformare array paralleli in array di record Un array è una struttura di dati omogenea: gli elementi dell array sono tutti dello stesso tipo (che è il tipo dell array). A volte è necessario gestire informazioni

Dettagli

n n 1 n = > Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita

n n 1 n = > Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita n! = 1 n( n 1)! se se n n = > 0 0 dove n è un numero intero non negativo Il calcolo del fattoriale

Dettagli

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati Algoritmi Ricorsivi e Maria Rita Di Berardini, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino A.A. 2006/07 I conigli di Fibonacci Ricerca Binaria L isola dei conigli

Dettagli

Un tipico esempio è la definizione del fattoriale n! di un numero n, la cui definizione è la seguente:

Un tipico esempio è la definizione del fattoriale n! di un numero n, la cui definizione è la seguente: Pag 29 4) La ricorsione 4.1 Funzioni matematiche ricorsive Partiamo da un concetto ben noto, quello delle funzioni matematiche ricorsive. Una funzione matematica è detta ricorsiva quando la sua definizione

Dettagli

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati Algoritmi e Strutture Dati Informazioni sul corso + Un introduzione informale agli algoritmi Domenico Fabio Savo 1 Domenico Fabio Savo Email: savo@dis.uniroma1.it Web: http://www.dis.uniroma1.it/~savo

Dettagli

Programmazione a Oggetti e JAVA. Prof. B.Buttarazzi A.A. 2012/2013

Programmazione a Oggetti e JAVA. Prof. B.Buttarazzi A.A. 2012/2013 Programmazione a Oggetti e JAVA Prof. B.Buttarazzi A.A. 2012/2013 Sommario La ricorsione Metodi ricorsivi Esercizi proposti 16/01/2013 2 La ricorsione In Java ogni metodo può chiamare anche se stesso,

Dettagli

Note per la Lezione 4 Ugo Vaccaro

Note per la Lezione 4 Ugo Vaccaro Progettazione di Algoritmi Anno Accademico 2016 2017 Note per la Lezione 4 Ugo Vaccaro Ripasso di nozioni su Alberi Ricordiamo che gli alberi rappresentano una generalizzazione delle liste, nel senso che

Dettagli

Calcolare x n = x x x (n volte)

Calcolare x n = x x x (n volte) Calcolare x n = x x x (n volte) Abbiamo bisogno di: una variabile ris in cui ad ogni iterazione del ciclo si ha un risultato parziale, e che dopo l ultima iterazione contiene il risultato finale; una variabile

Dettagli

Ordinamento per inserzione e per fusione

Ordinamento per inserzione e per fusione Ordinamento per inserzione e per fusione Alessio Orlandi 15 marzo 2010 Fusione: problema Problema Siano A e B due array di n A e n B interi rispettivamente. Si supponga che A e B siano ordinati in modo

Dettagli

Capitolo 19. Ricorsione

Capitolo 19. Ricorsione Capitolo 19 La ricorsione Una funzione matematica è definita ricorsivamente quando nella sua definizione compare un riferimento a sé stessa Esempio: Funzione fattoriale su interi non negativi: f(n) = n!

Dettagli

Nell informatica esistono alcuni problemi particolarmente rilevanti, poiché essi:

Nell informatica esistono alcuni problemi particolarmente rilevanti, poiché essi: Pag 24 3) Il problema della ricerca Nell informatica esistono alcuni problemi particolarmente rilevanti, poiché essi: si incontrano in una grande varietà di situazioni reali; appaiono come sottoproblemi

Dettagli

Parte 2. Ricorsione. [M.C.Escher Drawing hands, 1948] - AA. 2012/13 2.1

Parte 2. Ricorsione. [M.C.Escher Drawing hands, 1948] - AA. 2012/13 2.1 Parte 2 Ricorsione - AA. 2012/13 [M.C.Escher Drawing hands, 1948] 2.1 Funzioni ricorsive Una funzione si dice ricorsiva se richiama se stessa, direttamente o indirettamente La ricorsione si dice diretta

Dettagli

Rappresentazione degli algoritmi

Rappresentazione degli algoritmi Rappresentazione degli algoritmi Universitá di Ferrara Ultima Modifica: 21 ottobre 2014 1 1 Diagramma di flusso Utilizzare il diagramma di flusso per rappresentare gli algoritmi che risolvono i seguenti

Dettagli

Un esempio di calcolo di complessità: insertion sort

Un esempio di calcolo di complessità: insertion sort Un esempio di calcolo di complessità: insertion sort Vediamo su un esempio come si può calcolare la complessità di un algoritmo... L esempio è un metodo semplice per ordinare arrays: insertion sort, o

Dettagli

Esempio : i numeri di Fibonacci

Esempio : i numeri di Fibonacci Esempio : i numeri di Fibonacci La successione di Fibonacci F 1, F 2,... F n,... è definita come: F 1 =1 F 2 =1 F n =F n 1 F n 2,n 2 Leonardo Fibonacci (Pisa, 1170 Pisa, 1250) http://it.wikipedia.org/wiki/leonardo_fibonacci

Dettagli

Lezione 4. Problemi trattabili e soluzioni sempre più efficienti. Gianluca Rossi

Lezione 4. Problemi trattabili e soluzioni sempre più efficienti. Gianluca Rossi Lezione 4 Problemi trattabili e soluzioni sempre più efficienti Gianluca Rossi Trattabile o intrattabile? Consideriamo ora il problema, ben noto a tutti gli studenti a partire dalla scuola media, di calcolare

Dettagli

n n 1 n = > Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita

n n 1 n = > Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita n! = 1 n( n 1)! se se n n = > 0 0 dove n è un numero intero non negativo Il calcolo del fattoriale

Dettagli

Tecniche Algoritmiche: divide et impera

Tecniche Algoritmiche: divide et impera Tecniche Algoritmiche: divide et impera Una breve presentazione F. Damiani - Alg. & Lab. 04/05 Divide et impera (o Divide and conquer) Per regnare occorre tenere divisi i nemici e trarne vantaggio F. Damiani

Dettagli

Lezione 8 programmazione in Java. Anteprima. La ricorsione. Nicola Drago Dipartimento di Informatica Università di Verona

Lezione 8 programmazione in Java. Anteprima. La ricorsione. Nicola Drago Dipartimento di Informatica Università di Verona Lezione 8 programmazione in Java Nicola Drago nicola.drago@univr.it Dipartimento di Informatica Università di Verona Anteprima Programmazione ricorsiva Fattoriale Somma di n numeri Torre di Hanoi Array

Dettagli

RICORSIONE. Informatica B - A.A. 2013/2014

RICORSIONE. Informatica B - A.A. 2013/2014 RICORSIONE Informatica B - A.A. 2013/2014 RICORSIONE Che cos è la ricorsione? Un sottoprogramma P richiama se stesso (ricorsione diretta) Un sottoprogramma P richiama un altro sottoprogramma Q che comporta

Dettagli

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve LE STRUTTURE DATI DINAMICHE: GLI ALBERI Cosimo Laneve 1 argomenti 1. definizione di alberi e nozioni relative 2. implementazione degli alberi, creazione, visita 3. algoritmo di visita iterativa e sua implementazione

Dettagli

Fondamenti di Informatica 6. Algoritmi e pseudocodifica

Fondamenti di Informatica 6. Algoritmi e pseudocodifica Vettori e matrici #1 Fondamenti di Informatica 6. Algoritmi e pseudocodifica Corso di Laurea in Ingegneria Civile A.A. 2010-2011 1 Semestre Prof. Giovanni Pascoschi Le variabili definite come coppie

Dettagli

Sistemi lineari. Lorenzo Pareschi. Dipartimento di Matematica & Facoltá di Architettura Universitá di Ferrara

Sistemi lineari. Lorenzo Pareschi. Dipartimento di Matematica & Facoltá di Architettura Universitá di Ferrara Sistemi lineari Lorenzo Pareschi Dipartimento di Matematica & Facoltá di Architettura Universitá di Ferrara http://utenti.unife.it/lorenzo.pareschi/ lorenzo.pareschi@unife.it Lorenzo Pareschi (Univ. Ferrara)

Dettagli

La ricorsione. Ver Claudio Fornaro - Corso di programmazione in C

La ricorsione. Ver Claudio Fornaro - Corso di programmazione in C La ricorsione Ver. 2.4 2010 - Claudio Fornaro - Corso di programmazione in C 2 Divide et impera Metodo di approccio ai problemi che consiste nel dividere il problema dato in problemi più semplici I risultati

Dettagli

Note per la Lezione 6 Ugo Vaccaro

Note per la Lezione 6 Ugo Vaccaro Progettazione di Algoritmi Anno Accademico 2016 2017 Note per la Lezione 6 Ugo Vaccaro Ancora sulla tecnica Programmazione Dinamica Nella lezione scorsa abbiamo appreso che la tecnica Divide-et-Impera,

Dettagli

Input. Il tipo char Alcune modalità di acquisizione di input. Laboratorio di Programmazione - Luca Tesei

Input. Il tipo char Alcune modalità di acquisizione di input. Laboratorio di Programmazione - Luca Tesei Input Il tipo char Alcune modalità di acquisizione di input 1 Lettura di dati in input Vediamo due modi per acquisire dei dati di input dall utente: 1. Tramite una finestra grafica di dialogo 2. Tramite

Dettagli

Algoritmi di ordinamento

Algoritmi di ordinamento Algoritmi di ordinamento! Selection Sort! Quick Sort! Lower bound alla complessità degli algoritmi di ordinamento Ordinamento 1 Selection Sort SelectionSort(dati[]) { for (i=0; idati.length-1; i++) { min

Dettagli

Corso di Fondamenti di Programmazione canale E-O. Un esempio. Funzioni ricorsive. La ricorsione

Corso di Fondamenti di Programmazione canale E-O. Un esempio. Funzioni ricorsive. La ricorsione Corso di Fondamenti di Programmazione canale E-O Tiziana Calamoneri Ricorsione DD Cap. 5, pp. 160-184 KP Cap. 5, pp. 199-208 Un esempio Problema: prendere in input un intero e calcolarne il fattoriale

Dettagli

7 - Programmazione procedurale: Dichiarazione e chiamata di metodi ausiliari

7 - Programmazione procedurale: Dichiarazione e chiamata di metodi ausiliari 7 - Programmazione procedurale: Dichiarazione e chiamata di metodi ausiliari Programmazione e analisi di dati Modulo A: Programmazione in Java Paolo Milazzo Dipartimento di Informatica, Università di Pisa

Dettagli

Definizione di metodi in Java

Definizione di metodi in Java Definizione di metodi in Java Un metodo in Java definisce un operazione ad alto livello (sottoprogramma) che consente di manipolare dati e oggetti. Durante la computazione effettuata da un programma, un

Dettagli

Funzioni e Ricorsione

Funzioni e Ricorsione Funzioni e Ricorsione La ricorsione consiste nella possibilità di definire una funzione in termini di se stessa Nel codice di una funzione ricorsiva compare una (o più di una) chiamata alla funzione stessa

Dettagli

Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base

Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base Dati e Algoritmi I (Pietracaprina): Esercizi 1 Problema 1. Sia T una stringa arbitraria di lunghezza n 1 su un alfabeto Σ. È sempre possibile

Dettagli

Problemi, istanze, soluzioni

Problemi, istanze, soluzioni lgoritmi e Strutture di Dati II 2 Problemi, istanze, soluzioni Un problema specifica una relazione matematica tra dati di ingresso e dati di uscita. Una istanza di un problema è formata dai dati di un

Dettagli

19 - Eccezioni. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

19 - Eccezioni. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo 19 - Eccezioni 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 Corso

Dettagli

Ricorsione. quindi si può definire n! mediante i seguenti due punti:

Ricorsione. quindi si può definire n! mediante i seguenti due punti: Ricorsione Due definizioni del fattoriale Prima definizione: n! = 1 2 3....(n-1) n Per la seconda definizione notiamo che 1 2 3.... n = (n-1)! n (n-1)! quindi si può definire n! mediante i seguenti due

Dettagli

Laboratorio di Python

Laboratorio di Python Problem solving, Ricorsione, Università di Bologna 13 e 15 marzo 2013 Sommario 1 2 3 4 Errore di semantica Esercizio def vocali(s): voc='' for c in s: if c in 'aeiou': voc=voc+c return voc Cerchiamo di

Dettagli

Linguaggio C. Problemi di Ricerca e Ordinamento: Algoritmi e Complessità.

Linguaggio C. Problemi di Ricerca e Ordinamento: Algoritmi e Complessità. Linguaggio C Problemi di Ricerca e Ordinamento: Algoritmi e Complessità. 1 Complessità degli Algoritmi Si definisce Complessità di un Algoritmo C(A) la funzione dei parametri rilevanti per A che determina

Dettagli

La ricorsione. Sommario. Fulvio CORNO - Matteo SONZA REORDA Dip. Automatica e Informatica Politecnico di Torino

La ricorsione. Sommario. Fulvio CORNO - Matteo SONZA REORDA Dip. Automatica e Informatica Politecnico di Torino La ricorsione Fulvio CORNO - Matteo SONZA REORDA Dip. Automatica e Informatica Politecnico di Torino Sommario! Definizione di ricorsione e strategie divide et impera! Semplici algoritmi ricorsivi! Merge

Dettagli

Heap e code di priorità

Heap e code di priorità Heap e code di priorità Violetta Lonati Università degli studi di Milano Dipartimento di Scienze dell Informazione Laboratorio di algoritmi e strutture dati Corso di laurea in Informatica AA 2009/2010

Dettagli

Appunti lezione Capitolo 14 Greedy

Appunti lezione Capitolo 14 Greedy Appunti lezione Capitolo 14 Greedy Alberto Montresor 21 Novembre, 2016 1 Domanda: dimostrare che S[i, j] = con i j Nel problema della selezione delle attività, il sottoinsieme S[i, j] è definito nel modo

Dettagli

Corso di Programmazione Problem Solving. Tipi di Problemi. Problemi Complessi Soluzione. Dott. Pasquale Lops. Primitivi. Complessi

Corso di Programmazione Problem Solving. Tipi di Problemi. Problemi Complessi Soluzione. Dott. Pasquale Lops. Primitivi. Complessi Materiale didattico preparato dal dott. Stefano Ferilli Corso di Programmazione Problem Solving Dott. Pasquale Lops lops@di.uniba.it Corso di Programmazione - DIB 1/30 Tipi di Problemi Primitivi Risolubili

Dettagli

Algoritmi e strutture dati

Algoritmi e strutture dati Algoritmi e Strutture Dati Capitolo 1 Un introduzione informale agli algoritmi Definizione informale di algoritmo Insieme di istruzioni, definite passo per passo, in modo da poter essere eseguite meccanicamente

Dettagli

Indice. Prefazione. 3 Oggetti e Java 53

Indice. Prefazione. 3 Oggetti e Java 53 Prefazione xv 1 Architettura dei calcolatori 1 1.1 Calcolatori e applicazioni 1 1.1.1 Alcuni esempi di applicazioni 3 1.1.2 Applicazioni e interfacce 4 1.2 Architettura dei calcolatori 7 1.2.1 Hardware

Dettagli

Algoritmi di ricerca. Per ricerca si intende qui il procedimento di localizzare una particolare informazione in un elenco di dati.

Algoritmi di ricerca. Per ricerca si intende qui il procedimento di localizzare una particolare informazione in un elenco di dati. E. Calabrese: Fondamenti di Informatica Algoritmi-1 Algoritmi di ricerca Per ricerca si intende qui il procedimento di localizzare una particolare informazione in un elenco di dati. Per esempio: - cercare

Dettagli

Laboratorio di Algoritmi e Strutture Dati

Laboratorio di Algoritmi e Strutture Dati Laboratorio di Algoritmi e Strutture Dati Docente: Camillo Fiorentini 8 gennaio 8 Il problema è simile all esercizio 5.6 del libro di testo di algoritmi (Introduzione agli algoritmi e strutture dati, T.

Dettagli

Algoritmi e Strutture Dati. Capitolo 4 Ordinamento: Selection e Insertion Sort

Algoritmi e Strutture Dati. Capitolo 4 Ordinamento: Selection e Insertion Sort Algoritmi e Strutture Dati Capitolo 4 Ordinamento: Selection e Insertion Sort Ordinamento Dato un insieme S di n elementi presi da un dominio totalmente ordinato, ordinare S in ordine non crescente o non

Dettagli

I numeri rossi sulla Mole Antonelliana a Natale. Algoritmi e Laboratorio a.a Lezioni. Le regole della riproduzione dei conigli.

I numeri rossi sulla Mole Antonelliana a Natale. Algoritmi e Laboratorio a.a Lezioni. Le regole della riproduzione dei conigli. I numeri rossi sulla Mole Antonelliana a Natale Università di Torino acoltà di Scienze MN Corso di Studi in Informatica Curriculum SR (Sistemi e Reti) Algoritmi e Laboratorio a.a. 29- Lezioni prof. Elio

Dettagli

6 - Blocchi e cicli. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

6 - Blocchi e cicli. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo 6 - Blocchi e cicli Programmazione e analisi di dati Modulo A: Programmazione in Java Paolo Milazzo Dipartimento di Informatica, Università di Pisa http://pages.di.unipi.it/milazzo milazzo di.unipi.it

Dettagli

Creazione, eliminazione, lettura e scrittura di file di testo

Creazione, eliminazione, lettura e scrittura di file di testo Creazione, eliminazione, lettura e scrittura di file di testo Creazione Java mette a disposizione degli sviluppatori diverse classi per lavorare con i file di testo, analizziamo le principali: java.io.file

Dettagli

Ricerca lineare: elementi ripetuti

Ricerca lineare: elementi ripetuti Ricerca lineare: elementi ripetuti Ricerca lineare: elementi ripetuti II caso. Supponiamo che gli elementi di A non siano tutti distinti tra loro e che vogliamo conoscere dove si trova l elemento: dovremo

Dettagli

Algoritmi e strutture di dati 2

Algoritmi e strutture di dati 2 Algoritmi e strutture di dati 2 Paola Vocca Lezione 1: Divide et Impera 1 Paradigma del divide et impera Strutturato in tre fasi. Sia Π() istanza di dimensione di un problema computazionale Π (dove è immediato

Dettagli

Appunti sui Codici di Reed Muller. Giovanni Barbarino

Appunti sui Codici di Reed Muller. Giovanni Barbarino Appunti sui Codici di Reed Muller Giovanni Barbarino Capitolo 1 Codici di Reed-Muller I codici di Reed-Muller sono codici lineari su F q legati alle valutazioni dei polinomi sullo spazio affine. Per semplicità

Dettagli

Albero di Riscorsione

Albero di Riscorsione Albero di Riscorsione Albero di ricorsione Un albero di ricorsione è un modo di visualizzare cosa accade in un algoritmo divide et impera L etichetta della radice rappresenta il costo non ricorsivo della

Dettagli

Laboratorio di Informatica

Laboratorio di Informatica Laboratorio di Informatica Seconda lezione a Python Dottore Paolo Parisen Toldin - parisent@cs.unibo.it Dottoressa Sara Zuppiroli - sara.zuppiroli@unibo.it L'importanza di capire Perché non dobbiamo dichiarare

Dettagli

Conversione di base. Conversione decimale binario. Si calcolano i resti delle divisioni per due

Conversione di base. Conversione decimale binario. Si calcolano i resti delle divisioni per due Conversione di base Dato N>0 intero convertirlo in base b dividiamo N per b, otteniamo un quoto Q 0 ed un resto R 0 dividiamo Q 0 per b, otteniamo un quoto Q 1 ed un resto R 1 ripetiamo finché Q n < b

Dettagli

Gestione della produzione e della supply chain Logistica distributiva

Gestione della produzione e della supply chain Logistica distributiva Gestione della produzione e della supply chain Logistica distributiva Paolo Detti Dipartimento di Ingegneria dell Informazione e Scienze Matematiche Università di Siena Convergenza dell algoritmo Se non

Dettagli

Corso di Fondamenti di Informatica. La ricorsione

Corso di Fondamenti di Informatica. La ricorsione Corso di Fondamenti di Informatica La ricorsione La ricorsione Si dice che un oggetto (una struttura dati, una funzione matematica, un concetto ) è ricorsivo se è possibile darne una definizione in termini

Dettagli

Cammini minimi fra tutte le coppie

Cammini minimi fra tutte le coppie Capitolo 12 Cammini minimi fra tutte le coppie Consideriamo il problema dei cammini minimi fra tutte le coppie in un grafo G = (V, E, w) orientato, pesato, dove possono essere presenti archi (ma non cicli)

Dettagli

A.A CORSO DI ALGEBRA 1. PROFF. P. PIAZZA, E. SPINELLI. SOLUZIONE ESERCIZI FOGLIO 5.

A.A CORSO DI ALGEBRA 1. PROFF. P. PIAZZA, E. SPINELLI. SOLUZIONE ESERCIZI FOGLIO 5. A.A. 2015-2016. CORSO DI ALGEBRA 1. PROFF. P. PIAZZA, E. SPINELLI. SOLUZIONE ESERCIZI FOGLIO 5. Esercizio 5.1. Determinare le ultime tre cifre di n = 13 1625. (Suggerimento. Sfruttare il Teorema di Eulero-Fermat)

Dettagli

Programmazione dinamica

Programmazione dinamica Programmazione dinamica Violetta Lonati Università degli studi di Milano Dipartimento di Informatica Laboratorio di algoritmi e strutture dati Corso di laurea in Informatica Violetta Lonati Programmazione

Dettagli

Linguaggi di programmazione - Principi e paradigmi 2/ed Maurizio Gabbrielli, Simone Martini Copyright The McGraw-Hill Companies srl

Linguaggi di programmazione - Principi e paradigmi 2/ed Maurizio Gabbrielli, Simone Martini Copyright The McGraw-Hill Companies srl Approfondimento 2.1 Non è questo il testo dove trattare esaurientemente queste tecniche semantiche. Ci accontenteremo di dare un semplice esempio delle tecniche basate sui sistemi di transizione per dare

Dettagli

Università degli studi di Roma Tor Vergata Ingegneria Medica Informatica I Programma del Corso

Università degli studi di Roma Tor Vergata Ingegneria Medica Informatica I Programma del Corso Obiettivi Di seguito vengono riportate una serie di domande che possono essere poste durante la prova formale del corso. Le seguenti domande non sono da ritenersi esaustive ma esemplificative. 1. Architettura

Dettagli

UNIVERSITÀ DEGLI STUDI DI PAVIA FACOLTÀ DI INGEGNERIA. Algoritmi

UNIVERSITÀ DEGLI STUDI DI PAVIA FACOLTÀ DI INGEGNERIA. Algoritmi UNIVERSITÀ DEGLI STUDI DI PAVIA FACOLTÀ DI INGEGNERIA Algoritmi Algoritmi classici Alcuni problemi si presentano con elevata frequenza e sono stati ampiamente studiati Ricerca di un elemento in un vettore

Dettagli

Costo di esecuzione. Quanto costa? Spazio. Spazio e tempo. Università Roma La Sapienza Corsi di Laurea Informatica/Tecnologie Informatiche

Costo di esecuzione. Quanto costa? Spazio. Spazio e tempo. Università Roma La Sapienza Corsi di Laurea Informatica/Tecnologie Informatiche Università Roma La Sapienza Corsi di Laurea Informatica/Tecnologie Informatiche Quanto costa? Prof. Stefano Guerrini guerrini@di.uniroma1.it Programmazione II (can. P-Z) A.A. 2005-06 Cosa contribuisce

Dettagli

UNIVERSITÀ DEGLI STUDI DI PAVIA FACOLTÀ DI INGEGNERIA. Matlab: esempi ed esercizi

UNIVERSITÀ DEGLI STUDI DI PAVIA FACOLTÀ DI INGEGNERIA. Matlab: esempi ed esercizi UNIVERSITÀ DEGLI STUDI DI PAVIA FACOLTÀ DI INGEGNERIA Matlab: esempi ed esercizi Sommario e obiettivi Sommario Esempi di implementazioni Matlab di semplici algoritmi Analisi di codici Matlab Obiettivi

Dettagli

INPUT OUTPUT Programmazione in rete e laboratorio. Le operazioni di I/O avvengono attraverso stream (sequenze di byte)

INPUT OUTPUT Programmazione in rete e laboratorio. Le operazioni di I/O avvengono attraverso stream (sequenze di byte) INPUT OUTPUT 2004-05 Le operazioni di I/O avvengono attraverso stream (sequenze di byte) programma stream in lettura sorgente Programmazione in rete e laboratorio programma stream in scrittura destinazione

Dettagli

Implementazione dell albero binario in linguaggio C++

Implementazione dell albero binario in linguaggio C++ Implementazione dell albero binario in linguaggio C++ Costruire il programma per gestire le operazioni su un albero binario. Ogni nodo dell albero contiene un codice e una descrizione; il programma deve

Dettagli

DIPARTIMENTO DI ELETTRONICA, INFORMAZIONE E BIOINGEGNERIA. INFORMATICA B Ingegneria Elettrica. La ricorsione

DIPARTIMENTO DI ELETTRONICA, INFORMAZIONE E BIOINGEGNERIA. INFORMATICA B Ingegneria Elettrica. La ricorsione INFORMATICA B Ingegneria Elettrica La ricorsione Ricorsione Che cos è la ricorsione? Un sottoprogramma P richiama se stesso (ricorsione diretta) Un sottoprogramma P richiama un altro sottoprogramma Q che

Dettagli

Divide et impera su alberi

Divide et impera su alberi Divide et impera su alberi Caso base: peru = null o una foglia Decomposizione: riformula il problema per i sottoalberi radicati nei figli di u. Ricombinazione: ottieniilrisultatoconricombina 1 Decomponibile(u):

Dettagli

Alberi Binari di Ricerca

Alberi Binari di Ricerca Alberi Binari di Ricerca Algoritmi su gli alberi binari: visite Dato un puntatore alla radice di un albero vogliamo scandire in modo sistematico tutti i nodi di tale albero In una lista abbiamo una unica

Dettagli

3.4 Metodo di Branch and Bound

3.4 Metodo di Branch and Bound 3.4 Metodo di Branch and Bound Consideriamo un generico problema di Ottimizzazione Discreta dove X è la regione ammissibile. (P ) z = max{c(x) : x X} Metodologia generale di enumerazione implicita (Land

Dettagli

Equazioni di primo grado

Equazioni di primo grado Equazioni di primo grado 15 15.1 Identità ed equazioni Analizziamo le seguenti proposizioni: a ) cinque è uguale alla differenza tra sette e due ; b ) la somma di quattro e due è uguale a otto ; c ) il

Dettagli

RISOLUZIONE DI SISTEMI LINEARI

RISOLUZIONE DI SISTEMI LINEARI RISOLUZIONE DI SISTEMI LINEARI Algebra lineare numerica 1 La risoluzione di un sistema lineare è il nucleo principale del processo di risoluzione di circa il 70% di tutti i problemi reali Per la risoluzione

Dettagli

Analisi algoritmi ricorsivi e relazioni di ricorrenza

Analisi algoritmi ricorsivi e relazioni di ricorrenza Analisi algoritmi ricorsivi e relazioni di ricorrenza Punto della situazione Finora abbiamo affrontato: il tempo di esecuzione di un algoritmo, l analisi asintotica con le notazioni asintotiche e la tecnica

Dettagli

Ricorsione. La ricorsione consiste nella possibilità di definire una funzione in termini di se stessa

Ricorsione. La ricorsione consiste nella possibilità di definire una funzione in termini di se stessa Funzioni e Ricorsione La ricorsione consiste nella possibilità di definire una funzione in termini di se stessa È basata sul principio di induzione matematica: se una proprietà P vale per n=n 0 e si può

Dettagli

Laboratorio 8. Programmazione - CdS Matematica. Marco Virgulin 13 Gennaio 2015

Laboratorio 8. Programmazione - CdS Matematica. Marco Virgulin 13 Gennaio 2015 Laboratorio 8 Programmazione - CdS Matematica Marco Virgulin 13 Gennaio 2015 Esercizio di riepilogo. Generare N numeri reali in [0,1[ e scriverli su file. Leggere i valori dal file e inserirli in un albero

Dettagli

Studio delle successioni con il software

Studio delle successioni con il software Studio delle successioni con il software Abbiamo visto due possibili definizioni per alcune successioni: diretta e per ricorrenza (o ricorsiva). Ricordiamo che la successione delle somme dei primi n numeri

Dettagli

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco.

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco. Alberi Alberi Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo Fosco Dora Drogo Dudo Frodo Daisy Alberi Gli alberi sono una generalizzazione

Dettagli

Problemi, algoritmi, calcolatore

Problemi, algoritmi, calcolatore Problemi, algoritmi, calcolatore Informatica e Programmazione Ingegneria Meccanica e dei Materiali Università degli Studi di Brescia Prof. Massimiliano Giacomin Problemi, algoritmi, calcolatori Introduzione

Dettagli

Algoritmi e Strutture Dati - II modulo Soluzioni degli esercizi

Algoritmi e Strutture Dati - II modulo Soluzioni degli esercizi Algoritmi e Strutture Dati - II modulo Soluzioni degli esercizi Francesco Pasquale 6 maggio 2015 Esercizio 1. Su una strada rettilinea ci sono n case nelle posizioni 0 c 1 < c 2 < < c n. Bisogna installare

Dettagli

Insegnamento di Laboratorio di algoritmi e strutture dati

Insegnamento di Laboratorio di algoritmi e strutture dati Insegnamento di Laboratorio di algoritmi e strutture dati Roberto Posenato ver. 0.6, 31/01/2008 1 / 25 Si comincia... 1 Esigenza... Definizione Tipi di eccezioni Sollevare eccezioni Gestire le eccezioni

Dettagli

Fondamenti di Informatica. Algoritmi di Ricerca e di Ordinamento

Fondamenti di Informatica. Algoritmi di Ricerca e di Ordinamento Fondamenti di Informatica Algoritmi di Ricerca e di Ordinamento 1 Ricerca in una sequenza di elementi Data una sequenza di elementi, occorre verificare se un elemento fa parte della sequenza oppure l elemento

Dettagli

GLI ALBERI BINARI DI RICERCA. Cosimo Laneve

GLI ALBERI BINARI DI RICERCA. Cosimo Laneve GLI ALBERI BINARI DI RICERCA Cosimo Laneve argomenti 1. alberi binari di ricerca 2. la ricerca di elementi e la complessità computazionale 3. operazione di cancellazione di elementi 4. esempi/esercizi

Dettagli

Laboratorio di Python

Laboratorio di Python Laboratorio di Python Alberi binari Lab15 12 Maggio 2017 Outline Correzione esercizi per oggi Alberi binari Teoria Esercizi Esercizi per casa Saluti Esercizio 1 per casa Scrivere una funzione palindroma(s)

Dettagli

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati Heap Maria Rita Di Berardini, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino A.A. 2006/07 Heap Heap binari: definizione Un heap binario è una struttura dati composta

Dettagli

Problemi e algoritmi. Il che cosa ed il come. Il che cosa ed il come. Il che cosa e il come

Problemi e algoritmi. Il che cosa ed il come. Il che cosa ed il come. Il che cosa e il come Problemi e algoritmi Il che cosa e il come Problema: descrive che cosa si deve calcolare Specifica (di un algoritmo): descrive che cosa calcola un algoritmo Algoritmo: descrive come effettuare un calcolo

Dettagli

Laboratorio di Programmazione M-Z

Laboratorio di Programmazione M-Z Diretta Laboratorio di Programmazione M-Z Docente: Dott.ssa Alessandra Lumini alessandra.lumini@unibo.it Università di Bologna, Sede di Cesena Divide et impera Dividere un problema in sottoproblemi più

Dettagli

Fondamenti di Informatica - 1. Prof. B.Buttarazzi A.A. 2011/2012

Fondamenti di Informatica - 1. Prof. B.Buttarazzi A.A. 2011/2012 Fondamenti di Informatica - 1 Prof. B.Buttarazzi A.A. 2011/2012 Sommario Operatore? Tipo di dato: struct La ricorsione Funzioni ricorsive Esercizi proposti 26/04/2012 2 Operatore? L'operatore? può essere

Dettagli

Introduzione alla programmazione

Introduzione alla programmazione Introduzione alla programmazione Risolvere un problema Per risolvere un problema si procede innanzitutto all individuazione Delle informazioni, dei dati noti Dei risultati desiderati Il secondo passo consiste

Dettagli

11.4 Chiusura transitiva

11.4 Chiusura transitiva 6 11.4 Chiusura transitiva Il problema che consideriamo in questa sezione riguarda il calcolo della chiusura transitiva di un grafo. Dato un grafo orientato G = hv,ei, si vuole determinare il grafo orientato)

Dettagli

Def. 1. Si chiamano operazioni elementari sulle righe di A le tre seguenti operazioni:

Def. 1. Si chiamano operazioni elementari sulle righe di A le tre seguenti operazioni: Facoltà di Scienze Statistiche, Algebra Lineare 1 A, G.Parmeggiani LEZIONE 5 Operazioni elementari sulle righe di una matrice Sia A una matrice m n. Def. 1. Si chiamano operazioni elementari sulle righe

Dettagli

Parte III: Algoritmo di Branch-and-Bound

Parte III: Algoritmo di Branch-and-Bound Parte III: Algoritmo di Branch-and-Bound Divide et Impera Sia z * max {c T x : x S} (1) un problema di ottimizzazione combinatoria difficile da risolvere. Domanda: E possibile decomporre il problema (1)

Dettagli

Corso di Perfezionamento

Corso di Perfezionamento Programmazione Dinamica 1 1 Dipartimento di Matematica e Informatica Università di Camerino 15 febbraio 2009 Tecniche di Programmazione Tecniche di progettazione di algoritmi: 1 Divide et Impera 2 Programmazione

Dettagli