La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

1 Master in BIOINFORMATICA Corso propedeutico di Informatica DOCENTE: Elisa Tiezzi UNIVERSITA DI SIENA.

Presentazioni simili


Presentazione sul tema: "1 Master in BIOINFORMATICA Corso propedeutico di Informatica DOCENTE: Elisa Tiezzi UNIVERSITA DI SIENA."— Transcript della presentazione:

1 1 Master in BIOINFORMATICA Corso propedeutico di Informatica DOCENTE: Elisa Tiezzi UNIVERSITA DI SIENA

2 2 Programma Introduzione allinformatica Cosè linformatica Introduzione al concetto di algoritmo Struttura dellelaboratore Introduzione al concetto di programma Esecuzione delle istruzioni Lorganizzazione dellunità centrale di elaborazione (CPU) La memoria centrale La memoria secondaria Dispositivi di input/output Linguaggi di programmazione Introduzione ai linguaggi di programmazione

3 3 Elementi del Linguaggio Java l Ambiente di lavoro l Struttura di un programma l Tipi di dati fondamentali l Istruzioni di input/output l Costrutto decisionale if-then-else l I cicli con contatore for l Cicli condizionali while l Dati strutturati: stringhe e vettori l Cicli for annidiati l Classi e oggetti l Implementazioni di algoritmi Introduzione alla Complessità l Complessità di problemi l Analisi del caso medio e caso pessimo l Valutazione della complessità: relazioni di ricorrenza Progetto e analisi di alcuni algoritmi di Ordinamento l Ricorsività l Divide et impera l Mergesort l Quicksort Sistemi operativi l Windows

4 4 LIBRO UTILI JAVA Fondamenti di Progettazione software John Lewis, William Loftus ADDISON-WESLEY Java: An introduction to computer science and programming, 2 edizione Walter Savitch Prentice-Hall, Inc

5 5 INFORMATICA Alla metà del 900 il MONDO dellINFORMAZIONE diviene importante. INFORMATICA = insieme degli strumenti teorici e pratici che hanno lo scopo di elaborare linformazione. Il termine corrisponde al francese INFORMATIQUE (contrazione di INFORMATION AUTOMATIQUE) che compare verso la metà degli anni sessanta. In realtà linformatica si occupa non solo dellelaborazione dei dati ma anche della scienza e dellingegneria dei calcolatori. Gli anglosassoni usano il termine COMPUTER SCIENCE per sottolineare questa seconda accezione.

6 6 Linformatica ha quindi due significati: Insiste sulloggetto = PROCEDURA EFFETTIVA O ALGORITMO Insiste sullo strumento = CALCOLATORE ELETTRONICO

7 7 Le radici dellalgoritmica sono antiche. Anche se il suo assetto teorico definitivo è stato raggiunto nella prima metà di questo secolo e le tecniche di progetto ed analisi di algoritmi hanno segnato progressi enormi con la recente diffusione di calcolatori elettronici, i primi esempi di algoritmi risalgono alle origini della storia delluomo e sono registrati in documenti di matematica antica. La parola ALGORITMO fu creata nel latino medievale per assonanza con il nome del matematico persiano Al-Khuwarizmi. ALGORITMO

8 8 Informalmente la parola algoritmo indica la specificazione dei passi elementari che un esecutore deve compiere per giungere alla soluzione di un problema. ALGORITMO = complesso di istruzioni…. precisamente determinato in maniera da non consentire situazioni di dubbio universalmente comprensibile nel senso che chiunque possa applicarle abbastanza generali da potersi applicare ad ogni problema di una data classe tali che applicate ai dati forniscano criteri per determinare quando la soluzione è raggiunta e questo avvenga in un numero finito di passi

9 9 Alcuni algoritmi I più antichi algoritmi non banali conosciuti oggi furono registrati dallo scriba egizio Ahmes (1650 a.c.) Algoritmo moltiplicazione (dati A E B risultato P) -poni P=0 assegnazione -finché A0 ripeti la sequenza iterazione se A è dispari allora addiziona B a P esecuzione dimezza A trascurando il resto condizionata raddoppia B

10 10

11 11

12 12 Definizione intuitiva di algoritmo Elenco finito di istruzioni che specificano una serie di operazioni, eseguendo le quali e possibile risolvere ogni istanza di un problema di un dato tipo

13 13 Proprietà degli algoritmi FINITI NON AMBIGUI GENERALI

14 14 Soluzione di ax 2 +bx+c=0 1. inizio dellalgoritmo; 2. acquisire dallesterno i valori dei coefficienti a, b e c; 3. calcolare il valore b 2 -4ac; 4. se, allora non esistono radici reali: eseguire 8; 5. se, allora x 1 =x 2 =-b/2a: eseguire 7; 6. se, allora x 1 =(-b+ )/2a e x 2 =(-b- )/2a; 7. comunicare allesterno i valori di x 1 ed x 2 ; 8. fine dellalgoritmo.

15 15 Descrizione degli algoritmi Diagramma a blocchi (flow chart): rappresentazione grafica di un algoritmo che indica il flusso delle trasformazioni descritte dallalgoritmo che devono essere eseguite a partire dai dati iniziali per ottenere i risultati finali.

16 16 Blocchi elementari begin end input output azione C vero falso

17 17 Esempio su ax 2 +bx+c=0 end begin a, b, c b 2 -4ac VF FV x 1 =-b/2a x 2 =-b/2a x 1 =(-b+ )/2a x 2 =(-b- )/2a radici c.c. x 1, x 2

18 18 Il gioco dei quindici Quindici oggetti, ad esempio fiammiferi, sono su una tavola. Il primo giocatore ne raccoglie 1, 2 o 3. Il secondo giocatore ne raccoglie a sua volta 1, 2 o 3. Quindi è ancora il primo giocatore a raccogliere 1, 2 o 3 fiammiferi. I giocatori alternano le loro mosse finchè sul tavolo non esistono più fiammiferi. Il giocatore che è costretto a raccogliere lultimo fiammifero è il perdente. Descrivere una strategia vincente per il primo giocatore.

19 19 Problema delle dodici monete Tra 12 monete di identico aspetto potrebbe nascondersene una falsa e pertanto di peso diverso. Disponendo di una bilancia a 2 piatti per confrontare gruppi di monete, si vuole individuare la moneta falsa e stabilire se essa pesi più o meno delle altre, mediante non più di 3 pesate.

20 20 Soluzione del gioco dei quindici Siano A il primo giocatore e B il secondo 1. Prima mossa: A raccoglie 2 fiammiferi 2. Mosse successive: se B raccoglie k fiammiferi (k<=3), allora A raccoglie 4-k fiammiferi

21 21 Soluzione del gioco delle monete 1, 2, 3, 4 : 5, 6, 7, 8 1, 2, 5 : 3, 4, 6 9, 10 : 11, 1 1:27:81:2 9:10 7P 8P 1L 9L0 1L 2L 3L 4L 5P 6P 7P 8P 1P 2P 3P 4P 5L 6L 7L 8L 9L 10L 11L 12L 9P 10P 11P 12P 0 1L 2L 6P5P 3L 4L5L 3P 4P 7L 8L 1P 2P 6L 9L 10L 11P 12L 12P 0 9P 10P 11l 7:83:4 6P2L8Pimp7P3L5P4L4P5L3P7Limp8L2P6L 12:19:10 11P10L12L12P10P11L9P 1P

22 22 Breve storia dei calcolatori Primi strumenti di calcolo meccanici –Abaco 1600 –Pascal (somma e sottrazione) –Leibniz (moltiplicazione e divisione) 1800 –Babbage (quadrato e stampa) –Babbage (macchina analitica) Ada Augusta Lovelace (prima programmatrice) –Schede perforate utilizzate nel 1890 (inizio di IBM)

23 –Mark I (primo calcolatore elettromeccanico) 1946 –ENIAC 1949 –EDSAC (macchina di tipo Von Neumann) Anni successivi –Stessa architettura ma tecnologia più avanzata 1960 –Internet (fine anni sessanta per esigenze militari, si chiamava Arpanet) 1989 –www (word wide web: enorme enciclopedia)

24 24 Hardware Pezzi fisici tangibili che supportano lelaborazione (chip di silicio, fili elettrici, tastiera, dischi, stampanti….) Software I componenti hardware sono inutili se non ricevono precise istruzioni. Un programma è una serie di istruzioni che lhardware esegue in sequenza.

25 25 Componenti hardware principali Dispositivi di input –Ad es.: mouse, tastiera Dispositivi di output –Ad es.: monitor, stampante Insieme in uno stesso contenitore –Processore (CPU) Central Processing Unit Interpreta e esegue le istruzioni –Memoria Organizzazione hardware standard Memoria Processore (CPU) Dispositivi di input Dispositivi di output

26 26 Due Tipi di Memoria Principale –area di lavoro –mantiene temporaneamente programmi e dati (mentre il programma è in esecuzione) Ausiliaria –permanente –salva programmi e risultati –Esempi: floppy & hard disk, CD, nastri

27 27 Organizzazione della Memoria Principale Bit = una cifra binaria –valori: 0 o 1 Byte = 8 bit La memoria principale è una lista di locazioni numerate ciascuna di un byte Il numero di byte utilizzato per memorizzare un dato varia con il tipo di dato

28 28 Radice Organizzazione della Memoria Ausiliaria FileDirectory File Directory File Directory

29 29 Programma Insieme di istruzioni che il calcolatore deve eseguire Calcolatore ProgrammaInputOutput

30 30 Tipi di Programmi Sistema Operativo –Programma supervisore DOS, Windows, MacOS, UNIX, Linux Applicazioni esistenti –word-processor/editor –web browser –compilatori o assembler Applicazioni create dallutente

31 31 Informazione Esistono due formati per memorizzare linformazione: ANALOGICO DIGITALE Linformazione analogica è continua La tecnologia digitale spezza e cresce proporzionalmente alla linformazione in tanti pezzi sorgente di informazione che rappresenta come numeri Es: termometro di mercurio, segnali Es: compact disc elettrici

32 32 I computer moderni sono digitali: Ogni tipo di informazione è spezzato in blocchi. Ogni blocco è rappresentato da un numero e linformazione è memorizzata sotto forma di sequenza di numeri. Il computer digitale memorizza linformazione sotto forma di numeri binari (base 2). La singola cifra binaria si chiama bit (binary digit). La base del sistema indica quante cifre si hanno a disposizione e il valore posizionale di ogni cifra in un numero.

33 33 Sistemi posizionali Il sistema di numerazione decimale è basato sullalfabeto decimale {0,1,2,3,4,5,6,7,8,9} ed ogni numero è rappresentato come sequenza di simboli di tale alfabeto. Ad ogni simbolo è associato un peso a seconda della posizione. Es: 2863=2x x x x10 0

34 34 In generale i sistemi numerici posizionali in base b 2 rappresentano ogni numero con m cifre in base b: N=c m-1 …….c 0 Dove i c i denotano elementi di un insieme di b simboli che corrispondono ai primi b numeri naturali 0…..b-1. Vale N=c i b i Es: =1x2 3 +1x2 2 +0x2 1 +0x2 0

35 35 Come comunicare Linguaggio macchina: –sequenze di 0 ed 1 –rigoroso –essenziale Linguaggio assembler: –simbolico –semplice traduzione aggiuntiva Linguaggio naturale: –linguaggio preferito dallessere umano –ambiguo, ridondante, non preciso Linguaggio di programmazione ad alto livello

36 36 Storia Moderna PASCAL (1970) Programming in Logic (1971) C (1974) ADA(1980)

37 37 Storia Contemporanea C++ (1985) Java (1994)

38 38 Tipi di programmazione Funzionale Logica Procedurale Orientata agli oggetti

39 39 Traduttori traduttore programma macchina Codice in l. macchina dati macchina Codice in l. macchina risultati

40 40 Compilatori ed interpreti Compilatore –programma che traduce un programma in linguaggio ad alto livello in un programma in linguaggio più semplice che il calcolatore può eseguire (più o meno) direttamente. Interprete –programma che traduce ed esegue una dopo laltra le istruzioni che compongono il programma sorgente

41 41 Lapproccio di Java Sia compilato che interpretato Codice intermedio: Byte Code –codice a basso livello portabile –simile al codice assembler ma indipendente dallhardware –invisibile ai programmatori Java Linterprete traduce dal byte code in un programma nel linguaggio macchina della macchina specifica

42 42 Lambiente Java Programma Java Compilatore Java Programma in Byte-Code Dati in input Esecuzione Interprete Programmi precedentemente compilati Output del Programma Java

43 43 Cosa è Java Linguaggio di programmazione familiare –Simile a C e C++ Linguaggio di programmazione orientato a oggetti –Facile da modificare e altamente riutilizzabile Linguaggio robusto –Restrizioni per evitare che le applicazioni generino errori Linguaggio ad alte prestazioni –Strumenti per la gestione di più processi Linguaggio portabile –Applicazioni eseguibili su Windows, Linux o MacOS Linguaggio semplice –Pochi strumenti base e molte librerie

44 44 Compilatori tradizionali codice sorgente compilatore Windows compilatore Linux compilatore MacOS codice eseguibile Windows codice eseguibile Linux codice eseguibile MacOS

45 45 Compilatore Java codice sorgente compilatore Windows compilatore Linux compilatore MacOS interprete bytecode Windows interprete bytecode Linux interprete bytecode MacOS Java bytecode

46 46 Programmazione Concetti base: –dati –istruzioni Dati: –variabili –tipi Istruzioni: –istruzioni base –strutture di controllo –sotto-programmi

47 47 Variabili e tipi Variabile: –locazione di memoria a cui è dato un nome con cui chiamarla ed utilizzarla programmatore usa il nome senza necessariamente sapere che esso faccia riferimento ad una locazione di memoria Tipo: –ogni variabile ha un tipo che indica che genere di dati la variabile può contenere una variabile può contenere dati di tipo intero (ad es., 15 o 2038), oppure dati di tipo carattere (ad es., a o £) oppure dati di tipo stringa (ad es., java o pascal)

48 48 Istruzioni base Assegnazioni ed espressioni: –comandi per leggere e scrivere dati in una variabile e per fare calcoli esempio: interest = amount * 0.07; Input/Output: –comandi per ricevere dati dallutente o da un file su disco e comandi per inviare dati nellaltra direzione

49 49 Strutture di controllo Un programma è una sequenza di istruzioni Il calcolatore esegue le istruzioni nellordine in cui esse appaiono, una dopo laltra –molto limitato Le strutture di controllo sono istruzioni speciali che consentono di modificare il normale flusso di istruzioni Due tipi base di strutture di controllo –cicli permettono di ripetere una sequenza di istruzioni –diramazioni permettono di decidere tra due o più diverse alternative di proseguimento

50 50 Sotto-programmi I programmi sono spesso abbastanza complessi da dover essere scomposti in pezzi più maneggevoli Un sotto-programma consiste di istruzioni per svolgere un certo compito raggruppate insieme in ununità a cui è dato un nome il nome può essere usato come sostituto dellintero insieme di istruzioni Esempio –uno dei compiti del programma consiste nel disegnare un rettangolo sullo schermo scrivere le necessarie istruzioni e raggrupparle in un sotto-programma di nome drawRect ogni volta che il programma deve disegnare un rettangolo, lo può fare con una semplice istruzione: drawRect(); Vantaggi: risparmio di scrittura, organizzazione, riutilizzo

51 51 Che cosa è una variabile? Una locazione in cui memorizzare dati ed a cui è assegnato un nome –un contenitore di dati Può contenere un solo tipo di dati –per esempio, solo numeri interi, solo numeri reali oppure solo caratteri

52 52 Creazione di variabili Tutte le variabili devono essere dichiarate prima di poterle utilizzare Una dichiarazione di variabile associa un nome alle locazioni di memoria ad essa corrispondenti e specifica il tipo di dati che la variabile conterrà: Tipo Variabile_1, Variabile_2, …; Per esempio, per creare tre variabili che memorizzino il numero di cesti, il numero di uova per cesto ed il numero totale di uova: int numberOfBaskets, eggsPerBasket, totalEggs;

53 53 Nomi di variabili: identificatori Regole - devono essere rispettate tutti gli identificatori Java devono obbedire alle stesse regole non devono cominciare con una cifra devono contenere solo numeri, lettere, simboli _ e $ (ma è meglio evitare $, in quanto è riservato per scopi particolari) sono sensibili alle maiuscole ( ThisName e thisName sono due diversi nomi di variabili) Regole di programmazione - dovrebbero essere rispettate usare sempre nomi che abbiano un significato (ad esempio, eggsPerBasket invece di n o di count ) iniziare i nomi di variabile con una lettera minuscola iniziare le parole interne al nome con una lettera maiuscola (meglio eggsPerBasket di eggsperbasket ) evitare di usare $ in quanto è riservato a scopi particolari

54 54 Due tipi di tipi di dati in Java primitivi I tipi più semplici Non possono essere decomposti in altri tipi Contengono solo valori Esempi: int - intero double - reale char - carattere classi Più complessi Composti di altri tipi (primitivi o classi) Contengono sia dati che metodi Esempio: Integer String

55 55 Tipi di Dati Primitivi

56 56 Quali sapere per ora int –semplicemente numeri interi –possono essere positivi e negativi –nessun punto decimale char –semplicemente un singolo carattere –utilizza le virgolette singole per esempio, `A`; double –numeri reali, sia positivi che negativi –ha un punto decimale (parte frazionaria) –due formati numero con punto decimale, a.e notazione e o scientifica, a.e e2, che significa x 10 2

57 57 Assegnare valori alle variabili Istruzione di assegnazione –variabile = espressione; esempio: answer = 42; Operatore di assegnazione: = –non lo stesso dellalgebra –significa: assegna il valore dellespressione alla destra del segno di uguale alla variabile alla sinistra. –se numberOfCards ha il valore 7 e handicap ha il valore 2, allora la seguente istruzione imposta il valore di score a 9: score = numberOfCards + handicap; La variabile può apparire in entrambi i lati: int count = 10; count = count - 1; –nuovo valore di count = = 9

58 58 Assegnare valori iniziali alle variabili I valori iniziali possono o meno essere assegnati quando le variabili sono dichiarate: int totalEggs, numberOfBaskets, eggsPerBasket; oppure int totalEggs = 0; int numberOfBaskets = 0; int eggsPerBasket = 0; Suggerimento: è una buona regola di programmazione inizializzare sempre le variabili.

59 59 Cambiare il valore di una variabile Generalmente il valore viene cambiato (è assegnato un valore diverso) in qualche parte del programma Può essere calcolato a partire da altri valori: totalEggs = numberOfBaskets * eggsPerBasket; Oppure può essere letto in input –vedremo più avanti

60 60 Operatori di assegnazione specializzati Unabbreviazione per eseguire unoperazione ed assegnare un nuovo valore ad una variabile Forma generale: var = expression; –equivalente a: var = var (expression); – è +, -, *, /, or % Esempi: amount += 5; //amount = amount + 5; amount *= 1 + interestRate; //amount = amount * (1 + interestRate); La parte destra è trattata come una singola unità (come se vi fossero delle parentesi)

61 61 Costanti Le costanti sono simili alle variabili, ma possono contenere un solo valore per tutta la durata della loro esistenza. In Java si dichiarano le costanti premettendo la parola chiave final. E convenzione usare lettere maiuscole. Es.: final int NUMERO_MASSIMO_POSTI = 427 E buona pratica usare costanti invece di valori numerici (letterali) perche si evita di modificarli inavvertitamente.

62 62 Valore di ritorno Le espressioni ritornano valori: il numero prodotto da unespressione è il valore di ritorno int numberOfBaskets, eggsPerBasket, totalEggs; numberOfBaskets = 5; eggsPerBasket = 8; totalEggs = numberOfBaskets * eggsPerBasket; –nellultima linea numberOfBaskets ritorna il valore 5 e eggsPerBasket ritorna il valore 8 –numberOfBaskets * eggsPerBasket è unespressione che ritorna il valore intero 40

63 63 Conversione di tipo La conversione di tipo cambia il tipo di dato di un valore –Non è possibile assegnare un valore di un tipo ad una variabile di un tipo diverso, a meno che non lo si converta in modo da coincidere con il tipo della variabile La conversione di tipo modifica solo il tipo del valore di ritorno, non il tipo della variabile –ad esempio: double x; int n = 5; x = n; poiché n è un int ed x è un double, il valore ritornato da n (non n ) deve essere convertito in un double prima di essere assegnato ad x

64 64 Conversione implicita La conversione di tipo è eseguita implicitamente (in modo automatico) quando un tipo più basso viene assegnato ad un tipo più alto secondo la seguente gerarchia: byte --> short --> int --> long --> float --> double Ad esempio: double x; int n = 5; x = n; –il valore di ritorno di n è convertito (in modo implicito) in un double, e quindi assegnato ad x –x contiene 5.0 –il tipo di dato della variabile n è invariato (ovvero ancora int )

65 65 Ancora conversione implicita Alcune espressioni includono valori di tipo diverso Tutti i valori sono automaticamente (in modo implicito) fatti avanzare al livello più alto prima di eseguire il calcolo del valore di ritorno Ad esempio: double a; int n = 2; float x = 5.1; double y = 1.33; a = (n * x)/y; –i valori di n ed x sono automaticamente convertiti al tipo double prima di eseguire la moltiplicazione e la divisione

66 66 Conversione esplicita La conversione esplicita è necessaria in tutti i casi non coperti da quella implicta Ad esempio: int points; double distance = 9.0; points = distance; –lultima istruzione è illegale (anche se la parte frazionaria è 0) Porre di fronte al valore il cui tipo deve essere convertito il nuovo tipo tra parentesi: points = (int)distance; –questistruzione è legale

67 67 Troncamento Conversione da reale ad intero non arrotonda, ma tronca –la parte frazionaria viene semplicemente ignorata Ad esempio: int numberOfDollars; double dinnerBill = 26.99; numberOfDollars = (int) dinnerBill; –il valore di numberOfDollars è ora 26

68 68 Divisione reale e divisione intera Se almeno uno dei valori che occorrono nella divisione è di tipo float o double, allora non si ha nessun troncamento (tutti i valori sono convertiti al tipo più alto) Il troncamento si verifica se tutti i valori sono interi Ad esempio: int a = 4, b =5, c; double x = 1.5, y; y = b/x; c = b/a; –il valore di y è mentre quello di c è 1

69 69 Caratteri come interi Il tipo di dati char memorizza un singolo carattere stampabile Ad esempio: char answer = `y`; I caratteri sono in realtà memorizzati come interi secondo un codice speciale –ogni carattere stampabile (lettera, cifra, segno di interpunzione, spazio e tabulazione) ha associato un codice intero distinto –i codici sono distinti a seconda delle maiuscole o delle minuscole ad esempio, 97 potrebbe essere il codice di a e 65 quello di A ASCII e Unicode sono due codici molto frequenti Unicode include tutti i codici ASCII più altri codici per linguaggi con alfabeto diverso da quello italiano Java usa Unicode

70 70 Conversione di carattere in intero La conversione di un valore di tipo char produce il suo codice Unicode Ad esempio, eseguendo le seguenti istruzioni char answer = `7`; int intAnswer = answer; il valore di intAnswer sarebbe 55 (non 7) in quanto 55 è il codice Unicode del carattere 7

71 71 Imprecisione di numeri in virgola mobile I calcolatori memorizzano i numeri utilizzando un numero fissato di bit, per cui non tutti i numeri reali possono essere codificati in modo esatto –un numero infinito di bit sarebbe richiesto per rappresentare in modo esatto ogni numero reale –ad esempio, se il calcolatore può rappresentare solo 10 cifre dopo il punto decimale, allora il numero reale 1/3= sarebbe memorizzato come (che non è esattamente 1/3) Gli interi, al contrario, sono memorizzati in modo esatto –se il valore 2 è assegnato ad una variabile di tipo int, il suo valore è esattamente 2

72 72 Loperatore di modulo: % Usato con i tipi interi a%b restituisce il resto della divisione di b per a Ad esempio: int a = 14; b = 4, c; c = a%b; –c ora ha il valore 2, che è il reso della divisione di 14 per 4 Ha molte applicazioni –consente di contare modulo 2, 3 o qualsiasi altro numero consente di distinguere numeri pari da numeri dispari –consente di eseguire unoperazione solo in corrispondenza dei multipli di un dato numero

73 73 Precedenze e parentesi Le espressioni Java soddisfano regole simili allalgebra dei numeri reali Si usano le parentesi per forzare la precedenza –Tranne i casi in cui la precedenza è corretta ed ovvia, conviene usare le parentesi per facilitare la lettura dellespressione

74 74 Operatori di incremento e decremento Utilizzati per aumentare o diminuire il valore di una variabile di 1 Incremento –++ ad esempio, count++; Decremento –-- ad esempio, count--; La variabile può essere incrementata (o decrementata) prima o dopo aver usato il suo valore attuale. Ad esempio, dopo int count=5; int n = 2*(++count); int m = 2*(count++); sia n che m hanno il valore 12, mentre count ha il valore 7

75 75 Controllo del flusso Flusso di esecuzione: ordine in cui le istruzioni di un programma sono eseguite Salvo contrordini, è in sequenza Due possibili alterazioni: –selezione: sceglie unazione da una lista di due o più azioni possibili –ripetizione: continua ad eseguire unazione fino a quando non si verifica una condizione di termine

76 76 Strutture Java Sequenza –di default l Selezione »if »if-else »switch l Ripetizione »while »do-while »for

77 77 Valori Booleani boolean: tipo di dato primitivo in Java che può assumere valore true oppure false Variabili (o espressioni) il cui valore è di tipo boolean sono chiamate variabili (o espressioni) Booleane –Il valore di una variabile (o espressione) Booleana è true oppure false

78 78 Espressioni Booleane Esprimono una condizione che risulta essere vera o falsa Esempio (A e B sono due dati non necessariamente dello stesso tipo): –A è maggiore di B? –A è uguale a B? –A è minore di oppure uguale a B?

79 79 Operatori di confronto

80 80 Confronto tra caratteri e stringhe Si può confrontare caratteri: sono infatti basati su Unicode che definisce un ordinamento per tutti i possibili caratteri che possono essere usati. Dato che in Unicode, per esempio, il carattere a viene prima di b, si può dire che a è minore di b. Non si possono usare operatori di confronto e di uguaglianza tra stringhe.

81 81 Confronto tra valori in virgola mobile Raramente si usa loperatore di uguaglianza tra due valori in virgola mobile. Per testare luguaglianza di due valori in virgola mobile si può calcolare il valore assoluto della loro differenza e confrontare il valore così ottenuto con un valore di tolleranza, ad esempio 0,00001.

82 82 Operatori logici AND: && –congiunge due espressioni –valore di ritorno true se e solo se entrambi le espressioni sono vere OR: || –disgiunge due espressioni –valore di ritorno false se e solo se entrambi le espressioni sono false Valutazione della seconda espressione condizionata –per avere valutazione completa, usare & e |

83 83 Altri operatori logici NOT: ! –nega unespressione –valore di ritorno true se e solo se lespressione è falsa XOR: ^ –disgiunge due espressioni in modo esclusivo –valore di ritorno true se e solo se le due espressioni hanno diversi valori di ritorno –esprimibile mediante AND, OR e NOT

84 84 Precedenze e associatività Unario ! Unario postfisso assegnazione = += -= *= /= %= &= |= ^= OR || AND && OR | XOR ^ AND & Uguaglianza = = != Relazionale >= Additivo + - Moltiplicativo * / % Conversione (type) Operatori Associatività Tipo

85 85 Esempio score 90 (score 90) ((score 90))

86 86 Blocchi di istruzioni Insiemi di istruzioni racchiuse tra parentesi graffe –corrispondono ad unazione –parentesi non necessarie se include una sola istruzione Esempio: { //inizio del blocco calorieLess = 500; calorieAllotment = calorieAllotment-calorieLess; } //fine del blocco

87 87 Istruzione if Selezione semplice: –esegue unazione se solo se una certa condizione è verificata Sintassi: if (Espressione_Booleana) Blocco_1 //esegui solo se vera Prossima_Istruzione; //sempre eseguita Espressione_Booleana true Blocco_1 false Prossima_Istruzione

88 88 Esempio Se il peso è superiore a quello ideale allora diminuisci il numero totale di calorie che si possono assumere di 500. Successivamente, imposta il numero di calorie da assumere per colazione ad un terzo del numero totale di calorie if(weight > ideal) calorieAllotment = calorieAllotment-500; calorieBreakfast = calorieAllotment/3;

89 89 Istruzione if-else Selezione doppia: –esegue unazione oppure unaltra in base al valore di una condizione Sintassi: if (Espressione_Booleana) Blocco_1 //esegui solo se vera else Blocco_2 //esegui solo se falsa Prossima_Istruzione; //sempre eseguita

90 90 Diagramma di flusso Espressione_Booleana true Blocco_1 false Blocco_2 Prossima_Istruzione

91 91 Esempi Esempio con una singola istruzione: if(balance >=0) balance=balance+(INTEREST_RATE*balance)/12; else balance=balance-OVERDRAWN_PENALTY; Esempio con unistruzione composta: if(balance >=0) { interest=(INTEREST_RATE*balance)/12; balance=balance+interest; } else { interst=OVERDRAWN_PENALTY; balance=balance-interest; }

92 92 Istruzioni if-else annidate Annidamento di istruzioni if-else: –tratta situazioni con più di due possibilità –Attenzione : ogni else si riferisce allif più vicino Sintassi: if (Espressione_Booleana_1) Blocco_1 else if (Espressione_Booleana_2) Blocco_2. else if (Espressione_Booleana_ n) Blocco_n else Blocco_Default

93 93 Esempio if (score >= 90) grade = A; else if (score >= 80) grade = B; else if (score >= 70) grade = C; else if (score >= 60) grade = D; else grade = E;

94 94 Istruzione switch Selezione multipla Sintassi: switch(Espressione_Di_Controllo) { case Etichetta_Caso_1: Sequenza_Istruzioni_1 break; case Etichetta_Caso_2: Sequenza_Istruzioni_2 break;... default: Sequenza_Istruzioni_Default }

95 95 Espressione_Di_Controllo deve essere char, int, short o byte Espressione_Di_Controllo e le varie Etichette_Caso_* devono essere dello stesso tipo Listruzione break, che può essere omessa, fa, passare il controllo alla prima istruzione dopo listruzione switch –se break non è inclusa, allora lesecuzione procede con le istruzioni del caso successivo

96 96 Diagramma di flusso Espressione_Di_Controllo = Etichetta_Caso_1 true Sequenza_Istruzioni_1 break? true break? Espressione_Di_Controllo = Etichetta_Caso_2 false Sequenza_Istruzioni_2 false... true false... false true Sequenza_Istruzioni_Default default?

97 97 Esempio switch (seatLocationCode) { case 1: type=O; price = 40.00; break; case 2: type=M; price = 30.00; break; case 3: case 4: type=B; price = 15.00; break; default: type=U; }

98 98 Loperatore condizionale È lunico operatore ternario di Java Sintassi: –(Espressione Booleana)? Espressione_1:Espressione_2; Il valore di ritorno è quello di Espressione_1 se Espressione Booleana è vera, altrimenti è quello di Espressione_2

99 99 Esempio max = (n1>n2)?n1:n2; Equivale a: if (n1>n2) max = n1; else max = n2;

100 100 Ripetizione: i cicli Struttura: –corpo del ciclo –condizione di terminazione del ciclo Organizzazione logica –cicli controllati da condizioni –cicli controllati da contatori Istruzioni Java per realizzare cicli –while –do-while –for

101 101 Ciclo while Sintassi: while (Espressione_Booleana) Blocco //corpo del ciclo Prossima_Istruzione Espressione_Booleana rappresenta la condizione di ripetizione del ciclo –si esce dal ciclo, quando è falsa Blocco rappresenta il corpo del ciclo Istruzioni di inizializzazione precedono generalmente il ciclo

102 102 true Blocco Diagramma di flusso Espressione_Booleana false Prossima_Istruzione

103 103 Esempio Ciclo che calcola la somma dei primi 10 numeri interi int total = 0; int count = 1; while (count <= 10) { total = total + count; count++; }

104 104 Minimo numero di iterazioni Il numero minimo di iterazioni di un ciclo while è 0 dato che la condizione di ingresso può essere immediatamente falsa Esempio: int next; int total = 0; next = (int)(Math.random()*100)-50; while (next >= 0) { total = total + next; next = (int)(Math.random()*100)-50; }

105 105 Ciclo do-while Sintassi: do Blocco //corpo del ciclo while (Espressione_Booleana); Prossima_Istruzione Il corpo del ciclo è eseguito almeno una volta dato che la condizione di ripetizione è posta dopo il corpo stesso

106 106 Diagramma di flusso Espressione_Booleana false Prossima_Istruzione Blocco true

107 107 Esempio int next; int total = 0; do { next = (int)(Math.random()*100)-50; total = total + next; } while (next >= 0);

108 108 Cicli infiniti Cause principali: –errata espressione Booleana –errata (o assente) alterazione delle variabili coinvolte nellespressione Booleana Esempio: int total = 0; int count = 1; while (count != 10) { total = total + count; count += 2; }

109 109 Ciclo for Struttura: –azione di inizializzazione –condizione di ripetizione –corpo del ciclo –azione di continuazione Sintassi: for (Inizializzazione; Espressione_Booleana; Continuazione) Blocco Prossima_Istruzione

110 110 Diagramma di flusso Inizializzazione Continuazione Blocco true Espressione_Booleana false Prossima_Istruzione

111 111 Esempio Sommare separatamente i numeri pari e quelli dispari compresi tra 1 e 100 int sumEven = 0, sumOdd = 0; for (int count = 1; count <= 99; count+=2) { sumOdd = sumOdd + count; sumEven = sumEven + count + 1; }

112 112 Considerazioni pratiche Errori comuni: –cicli infiniti (non intenzionali) –cicli con contatore che non eseguono il numero di iterazioni desiderato (scarto di uno). Testare soprattutto la condizione di ripetizione di un ciclo per evitare possibili errori Mantenere traccia dei valori delle variabili (facendo uso di stampe su video)

113 113 Questioni di stile Blocchi: { Sequenza_Istruzioni } –inserire le parentesi graffe anche se il blocco è costituito da una sola istruzione –indentare tutte le istruzioni incluse nella sequenza

114 114 Istruzione if: if (Espressione_Booleana) Blocco Istruzione if-else: if (Espressione_Booleana) Blocco else Blocco

115 115 Istruzione switch: switch (Espressione_Di_Controllo) { case Etichetta_1: Sequenza_Istruzioni_1 case Etichetta_2: Sequenza_Istruzioni_2... case Etichetta_n: Sequenza_Istruzioni_n default: Sequenza_Istruzioni_Default }

116 116 Istruzione while: while (Espressione_Booleana) Blocco Istruzione do-while: do Blocco while (Espressione_Booleana); Istruzione for: for (Inizializzazione ; EB; Continuazione) Blocco

117 117 Sotto-programmi Necessità di scomporre programmi complessi Sotto-programma: insieme di istruzioni a cui è dato un nome il nome usato come sostituto dellintero insieme di istruzioni Esempio –generare un numero intero casuale compreso tra 1 e 100 raggruppare le necessarie istruzioni in un sotto-programma di nome randomNumber ogni volta che il programma deve generare un numero intero casuale compreso tra 1 e 100, lo può fare con una semplice istruzione: randomNumber() Vantaggi: risparmio di scrittura, organizzazione, riutilizzo

118 118 Sotto-programmi in Java In Java, i sotto-programmi sono chiamati metodi Interfaccia (sintattica) di un metodo: –nome del metodo –input richiesto –output fornito Sintassi della dichiarazione: Tipo_Output Nome_Metodo(Lista_Input) Blocco // corpo del metodo

119 119 Tipologie di metodi Alcuni metodi (talvolta, detti funzioni) eseguono unazione e ritornano un singolo valore –esempio: il metodo randomNumber genera un numero intero casuale compreso tra 1 e 100 e ne ritorna il valore Altri metodi (talvolta, detti procedure) si limitano ad eseguire unazione –esempio: il metodo printWelcomeMessage stampa un messaggio di benvenuto

120 120 Tipo di ritorno dei metodi Sempre specificato Può essere: –tipo di dato primitivo (come char oppure int ) –classe (come String ) –void se nessun valore viene ritornato Un metodo (non void ) può essere usato ovunque è lecito usare il suo tipo di ritorno –esempio: int r = randomNumber();

121 121 Istruzione return I metodi che ritornano un valore devono eseguire, allinterno del corpo, unistruzione return che include il valore da ritornare Esempio: int randomNumber() { int r = 1+(int)(Math.random()*99); return r; }

122 122 Esempio di metodo void Definizione del metodo printWelcomeMessage : void printWelcomeMessage() { System.out.println(``Hello!); System.out.println(``Welcome to paradise!); } Questo metodo esegue unazione (stampa un messaggio di benvenuto) ma non ritorna alcun valore

123 123 Nomi di metodi Buone regole di programmazione: –verbi per nominare metodi senza un valore di ritorno realizzano un azione esempio: printIntegerNumber –nomi per nominare metodi con un valore di ritorno creano (ritornano) un dato, ovvero una cosa esempio: randomNumber –iniziare il nome di un metodo con una lettera minuscola

124 124 Parametri di un metodo Metodi più flessibili (e quindi più utili) con valori di input (detti valori passati o parametri) Parametri e loro tipi di dato specificati allinterno delle parentesi tonde successive al nome del metodo –questi sono i parametri formali lista di parametri separati da virgole Invocando un metodo, vanno inseriti (allinterno delle parentesi tonde) valori del tipo specificato e nellordine specificato –questi sono gli argomenti, o parametri attuali

125 125 Esempio Dichiarazione: int randomNumber(int min, int max) { return min+(int)(Math.random()*(max-min)); } –parametri formali: min e max Invocazione: int m = 10; int M = 20; int r = randomNumber(m, M); –argomenti: m ed M

126 126 Passaggio per valore Parametri formali sono locali al loro metodo –variabili usate come argomenti non possono essere modificate dal metodo metodo riceve solo il loro valore Quando un metodo è invocato, il valore di ciascun argomento è copiato nel (assegnato al) corrispondente parametro formale –numero di argomenti uguale a numero di parametri formali –tipo di dati degli argomenti uguale a quello dei corrispondenti parametri formali –parametri formali inizializzati con i valori passati

127 127 Variabili locali ad un blocco Variabile dichiarata allinterno di un blocco: –vista solo allinterno del blocco locale al blocco, per cui è chiamata variabile locale se il blocco è il corpo di un metodo, la variabile è detta essere una variabile locale del metodo –quando il blocco termina lesecuzione, le variabili locali spariscono riferimenti a variabili locali fuori del blocco corrispondente causano errori di compilazione Variabile dichiarata nellinizializzazione di un for è locale al ciclo for –non può essere usata fuori del ciclo

128 128 Quando e dove Dichiarare una variabile fuori di tutti i blocchi ma allinterno di un metodo la rende disponibile a tutti i blocchi del metodo Buone regole di programmazione –dichiarare le variabili immediatamente prima di utilizzarle –inizializzare le variabili al momento della dichiarazione –non dichiarare variabili allinterno di cicli richiede tempo la creazione e la distruzione di una variabile eccezione: variabili dichiarate nellinizializzazione di un ciclo for

129 129 Programmazione procedurale Obiettivo –Concepire la costruzione di programmi di grande dimensione e complessità come composizione di componenti (procedure) costruite ad hoc esistenti Vantaggi –dominare la complessità –ridurre i costi –aumentare parallelismo nello sviluppo

130 130 Scomporre e comporre Principio del divide et impera Suddividere per isolare parti il più possibile autonome ed indipendenti Parti potenzialmente riutilizzabili

131 131 Autonomia ed indipendenza Ogni parte deve avere una sua coesione da un punto di vista logico –deve rappresentare unastrazione significativa Ogni parte deve essere il più possibile indipendente dalle altre parti

132 132 Procedura È una parte del sistema complessivo Deve avere, rispetto alle altre parti, uninterfaccia ben definita –interfaccia: tutto ciò che è necessario conoscere per poter usare la procedura

133 133 Procedure e metodi Un metodo Java può essere considerato come una procedura La sua interfaccia è specificata nellintestazione È bene che non modifichi variabili che non sono locali –indipendenza dalle altre procedure

134 134 Relazione di utilizzo Procedura A usa procedura B se, per svolgere il proprio compito, deve accedere alla procedura B attraverso quanto definito nellinterfaccia di questultima –esempio: se il metodo F invoca il metodo G, allora F usa G

135 135 Interfaccia/implementazione Occorre distinguere tra questi due aspetti Interfaccia –dice ciò che le altre procedure possono conoscere Implementazione –è come ciò che viene offerto attraverso linterfaccia è effettivamente realizzato

136 136 Struttura di un programma Procedura principale Più procedure asservite a quella principale Ciascuna di questultime, a sua volta, ne può usare altre

137 137 Una visione grafica procedura principale procedura asservita P1 procedura asservita P2 procedura asservita P4 procedura asservita P3 AB A usa B procedura asservita P5

138 138 Realizzazione in Java Procedura principale –procedura main Per ciascuna procedura asservita –interfaccia dichiarazione –implementazione definizione del corpo

139 139 Esempio Programma che genera due frazioni Decide se sono –apparenti: numeratore multiplo di denominatore –proprie: numeratore minore di denominatore Confronta le due frazioni Riduce le due frazioni ai minimi termini Riduce le due frazioni allo stesso denominatore Esegue le quattro operazioni

140 140 Struttura (parziale) main isApparentisProperisFETS isFBTS computeRN computeRD computeGCD

141 141 Frazioni apparenti e proprie boolean isApparent(int n, int d) { return (n % d == 0); } boolean isProper(int n, int d) { return (n < d); }

142 142 Confronto tra frazioni boolean isFETS(int n1,int d1,int n2,int d2) { return (n1*d2 == n2*d1); } boolean isFBTS(int n1,int d1,int n2,int d2) { return (n1*d2 > n2*d1); }

143 143 Calcolo del MCD (1) int computeGCD(int n, int d){ int count = 2, min = n, GCD = 1; if (n > d) min = d; while (count <= min) { if ((n%count == 0) && (d%count == 0)) GCD = count; ++count; } return GCD; }

144 144 Semplificazione di frazioni int computeRN(int n, int d) { return (n / computeGCD(n, d)); } int computeRD(int n, int d) { return (d / computeGCD(n, d)); }

145 145 Procedura principale void main() { int n1 = 1+(int)(Math.random()*99); int d1 = 1+(int)(Math.random()*99); int n2 = 1+(int)(Math.random()*99); int d2 = 1+(int)(Math.random()*99);... }

146 146 Calcolo del MCD (2) int computeGCD(int n, int d){ int GCD = n; if (n > d) GCD = d; while (GCD > 1) { if ((n%GCD == 0) && (d%GCD == 0)) break; --GCD; } return GCD; }

147 147 Algoritmo di Euclide Proprietà: –se r è il resto della divisione di a per b (a b), allora i divisori comuni di a e b coincidono con quelli di b ed r –MCD(a, b) = MCD(b, r) dove r = a mod b Algoritmo: –se b=0, allora MCD(a, b) = a, altrimenti MCD(a, b) = MCD(b, a mod b)

148 148 Calcolo del MCD (3) int computeGCD(int n, int d) { int temp = 0; while (d > 0) { temp = d; d = n % d; n = temp; } return n; }

149 149 Ricorsione Strumento potente per definizioni matematiche Possibilità di definire insieme infinito di oggetti con regola finita –possibilità di descrivere un insieme infinito di computazioni con un programma finito

150 150 Ricorsione in matematica Le formule matematiche sono spesso espresse in termini ricorsivi Esempio: definizione di fattoriale 1!=1 N!=N * (N-1)!

151 151 Metodi ricorsivi Contengono riferimenti espliciti a sé stessi –direttamente ricorsivi Un metodo ne invoca un altro e lesecuzione di questultimo porta ad un certo punto ad invocare nuovamente (direttamente o indirettamente) il metodo originale –indirettamente ricorsivi

152 152 Ricorsione infinita Requisito fondamentale: –chiamata ricorsiva subordinata ad una condizione che ad un certo istante deve divenire non soddisfatta Qualsiasi definizione ricorsiva deve avere una parte non ricorsiva, detta base della ricorsione, che permette alla ricorsione stessa di terminare Nellesempio precedente del fattoriale la base è 1! che è posto uguale ad 1

153 153 Variabili in metodi ricorsivi Ogni invocazione genera un nuovo insieme di variabili locali Ogni parametro riceve un valore iniziale in base alla nuova invocazione Ogni volta che il metodo termina si ritorna al metodo che lo ha chiamato ( che potrebbe essere lo stesso)

154 154 Numeri di Fibonacci Schema più complicato di composizione ricorsiva che potrebbe (e dovrebbe) essere tradotto in forma iterativa Definizione: –fib 0 = 0 –fib 1 = 1 –fib n+1 = fib n + fib n-1

155 155 Implementazione ricorsiva int computeFib(int n) { if (n == 0) return 0; if (n == 1) return 1; return computeFib(n-1)+computeFib(n-2); }

156 Numero di invocazioni Numero totale di invocazioni cresce esponenzialmente

157 157 Implementazione iterativa int computeFib(int n) { int i = 1, x = 1, y = 0; while (i < n) { i = i+1; x = x+ y; y = x -y; } return x; }

158 158 Considerazioni Ricorsione deve essere evitata se esiste una soluzione iterativa ovvia Non vuol dire evitare la ricorsione a qualunque costo –esistono molte buone applicazioni della ricorsione –algoritmi per loro natura ricorsivi vanno implementati con metodi ricorsivi

159 159 Le torri di Hanoi inventato nel 1880 da Lucas Tre aste (o torri) ed n dischi di dimensioni diverse (con buco per inserirli nelle aste) Allinizio tutti i dischi sono nellasta 1 –in ordine decrescente di grandezza Obiettivo: portarli nella torre 3 rispettando le regole seguenti –nessun disco mai sopra uno più piccolo –si può spostare un solo disco alla volta –dischi sempre collocati su una torre (non a parte) –solo disco in cima ad una torre può essere spostato

160 160 Algoritmo ricorsivo Obiettivo: spostare k dischi da torre 1 a torre 3 Algoritmo: –Spostare k-1 dischi da torre originale a torre temporanea –Spostare 1 disco da torre originale a torre di destinazione –Spostare k-1 dischi da torre temporanea a torre di destinazione

161 161 Implementazione 1 void moveTowers(int k, int o,int d) { if (k > 0) { moveTowers(k-1, o, 6-o-d); System.out.println("Sposta da "+o+"a"+d); moveTowers(k-1,6-o-d,d); }

162 162 Programmazione OO Concetti base : –dati –istruzioni Dati: –variabili –tipi Istruzioni: –istruzioni base –strutture di controllo –sotto-programmi Dati Istruzioni = Metodi Programmazione Procedurale Dati Metodi = Classi Programmazione a Oggetti

163 163 Cosa è un oggetto Metodi (comportamenti) Variabili (stato) Un oggetto è una scatola software contenente variabili (che descrivono lo stato di un oggetto) e metodi (detti suoi membri, definiscono i comportamenti)

164 164 Esempio: i numeri razionali Variabili di istanza (campi): contengono i valori (lo stato) del numero razionale Istanza: un preciso oggetto Metodi di istanza: agiscono sul numero razionale 3 4 isBigger isEqual add sub div mul razionale 3/4 num div

165 165 Cosa è un messaggio altro oggetto utilizzato dal programma razionale 3/4 num den isBigger(razionale di confronto) Gli oggetti interagiscono e comunicano tra loro usando i messaggi per ottenere maggiori funzionalità e comportamenti più complessi

166 166 Usare gli oggetti Inviare un messaggio ad un oggetto significa invocare un metodo delloggetto Accedere alle variabili di istanza di un oggetto significa poter manipolare o ispezionare il loro valore Sintassi per invocare un metodo/accedere alle variabili di istanza di un oggetto: –allinterno della definizione di un oggetto: metodo(lista_di_parametri) variabile –allesterno della definizione di un oggetto (operatore.): riferimentoOggetto.metodo(lista_di_parametri) riferimentoOggetto.variabile

167 167 Cosa è una classe Una classe è un prototipo che definisce le variabili e i metodi comuni a tutti gli oggetti di un certo tipo. Una classe è solo il modello di un oggetto e pertanto non riserva spazio di memoria per i suoi dati. Ogni oggetto ha il suo spazio dati, un oggetto è unistanza di una classe.

168 168 Esempio isBigger isEqual add sub div mul classe Rational int num int den Tutti gli oggetti di tipo Rational possiedono i due campi interi num e den ed almeno i 6 metodi riportati

169 169 isBigger isEqual add sub div mul int num=8 int den=15 oggetto 8/15 istanza di Rational isBigger isEqual add sub div mul int num=4 int den=5 oggetto 4/5 istanza di Rational

170 170 Dichiarare una classe class nome_classe { // definizione variabili // definizione metodi } Esempio: class Rational { int num; int den; // definizione metodi }

171 171 Dichiarare un oggetto Sintatticamente la dichiarazione di un oggetto è del tutto analoga alla dichiarazione di una variabile di tipo primitivo Esempio: –Rational primoNumero; essendo Rational una classe La variabile dichiarata di tipo classe è un indirizzo ad unarea di memoria contenente loggetto vero e proprio

172 172 Istanza di un oggetto Loperatore new crea un oggetto del tipo indicato dal metodo che immediatamente segue Sintassi: –riferimentoOggetto = new NomeClasse(lista_di_parametri); essendo riferimento Oggetto una variabile di tipo NomeClasse Lesecuzione di una tale istruzione comporta: –lallocazione della memoria necessaria a contenere loggetto –lassegnazione a riferimento Oggetto dellindirizzo di inizio dellarea di memoria allocata –linizializzazione delle variabili di istanza delloggetto dettate dalla lista di parametri del metodo NomeClasse(lista_di_parametri)

173 173 Fondere le due fasi Rational primoNumero; primoNumero = new Rational(3,4); è equivalente a Rational primoNumero = new Rational(3,4);

174 174 Oggetti e metodi Un metodo può ritornare il riferimento ad un oggetto del tipo dichiarato dal valore di ritorno del metodo –NomeClasse nomeMetodo(lista_input) Un metodo può avere un parametro formale di tipo classe. Al momento dellinvocazione di un tale metodo, il parametro è inizializzato con la copia –Rational mul(Rational number)

175 175 Tipi primitivi e tipo classe Un metodo non può cambiare il valore di una variabile di un tipo primitivo passatagli come argomento Un metodo può cambiare i valori delle variabili di istanza delloggetto indirizzato dalla variabile tipo classe che gli è passata come parametro

176 176 Il metodo main main è un metodo speciale dal quale le applicazioni Java iniziano automaticamente lesecuzione Sintassi: public static void main(String args) È buona norma non includere il metodo main nella definizione di una classe il cui scopo è esclusivamente quello di definire un tipo –eccezione: per debugging

177 177 Esempio: class RationalTest public static void main(String args) /* corpo del metodo main */

178 178 I costruttori Un costruttore è un metodo speciale designato a inizializzare le variabili di istanza –nome uguale a quello della classe Viene richiamato automaticamente quando loggetto è creato –new NomeClasse(lista_di_parametri) Un costruttore con una lista di argomenti vuota è detto costruttore di default Se nella classe non è presente un costruttore, Java crea automaticamente un costruttore di default

179 179 Definizione dei Costruttori La dichiarazione di un costruttore non include un tipo di ritorno che è comunque un indirizzo –è un errore anteporre la parola chiave void Esempio: class Rational int num, den; Rational(int n, int d) num = n; den = d;...

180 180 Un esempio riassuntivo class Rational int num, den; // variabili di istanza Rational(int n, int d) // costruttore num = n; den = d; Rational mul(Rational r) // operazione di moltiplicazione return new Rational(num*r.num,den*r.den); // altre operazioni aritmetiche boolean isBigger(Rational r) // confronto se maggiore return (num * r.den > den * r.num); // altre operazioni di confronto }

181 181 class RationalTest public static void main(String args) Rational firstNum = new Rational(3,5); Rational secondNum = new Rational(2,3); boolean isBiggerResult; isBiggerResult = firstNum.isBigger(secondNum); System.out.println (Primo>secondo:+isBiggerResult);

182 182 Firma (signature) di un metodo La firma di un metodo è data dal nome del metodo e dal numero, tipo e ordine dei suoi parametri –Esempio di firme diverse: int myMethod(int i) è diverso da int yourMethod(int i) int myMethod(int i) è diverso da int myMethod(int i, double j) int myMethod(int i, double j) è diverso da int myMethod(double j, int i) Il valore di ritorno di un metodo non fa parte della firma del metodo stesso –Esempio di firme uguali: int myMethod(int i) ha la stessa firma di double myMethod(int j)

183 183 Sovraccaricamento Lo stesso nome di un metodo ha più di una definizione allinterno della stessa classe I metodi sovraccarichi hanno lo stesso nome ma firme diverse tra loro –I costruttori sono spesso sovraccaricati

184 184 Esempio class MethodOverload int square(int x) return x*x; double square(double y) return y*y; int square(double x) return x*x; ………… sovraccaricamento errore segnalato dal compilatore

185 185 Sovraccaricamento e conversione Se non si ha la corrispondenza con una qualche firma, Java effettua conversioni di tipo automatiche per trovare uneventuale corrispondenza –una versione indesiderata del metodo può essere eseguita

186 186 INCAPSULAMENTO Le variabili contenute in un oggetto dovrebbero essere modificate solo dal suo interno, solo i metodi dovrebbero essere gli unici responsabili del cambiamento delle variabili. Un oggetto dovrebbe essere incapsulato rispetto a tutto il resto del sistema e dovrebbe interagire con le altre parti del programma solo attraverso un insieme specifico di metodi che definiscono i servizi che fornisce.

187 187 MODIFICATORI Un modificatore è una parola chiave di Java usata per specificare delle caratteristiche particolari di un costrutto del linguaggio. Alcuni modificatori sono chiamate modificatori di visibilità perché controllano fino a quale punto del programma è possibile usare un membro della classe.

188 188 Il modificatore public Il modificatore public indica la totale assenza di restrizioni di visibilità Le classi dichiarate public possono essere referenziate ovunque public class TwoDimensionalShape ………… class shapeTest TwoDimensionalShape myShape; ………… }

189 189 I campi ed i metodi dichiarati public sono accessibili ovunque public class A public int x; public int getX() return x; class B public static void main(String[] args) { A a = new A(); a.x = 3; System.out.println(a.getX()); }

190 190 Le variabili e i metodi dichiarati private sono accessibili soltanto dai metodi della classe in cui sono definiti Il modificatore private

191 191 Esempio public class TwoDimensionalShape private int width, height; private int generate( int n ) return 1+(int)( Math.random*n ); public void setRandomWidth( int n ) width = generate( n ); public int getWidth( ) { return width; } }

192 192 class shapeTest public static void main( String[] args ) { TwoDimensionalShape s = new TwoDimensionalShape(); s.width = s.generate( 100 ); ERRORE DOPPIO s.setRandomWidth( 100 ); System.out.println( s.getWidth( ) ); }

193 193 Caratteristiche dellOOP Occultamento delle informazioni protegge i dati allinterno di un oggetto –usa variabili di istanza private non permette un loro accesso diretto –usa metodi public per accedere alle variabili Incapsulamento gli oggetti incapsulano attributi e metodi nasconde i dettagli di una definizione di classe separando –interfaccia (API) –implementazione

194 194 La parola chiave static Una variabile definita static è detta variabile di classe Essa rappresenta informazioni valide per lintera classe ed è condivisa da tutte le istanze della classe Esempio: public class A static int x ; ………

195 195 Un metodo definito static è detto metodo di classe Esso definisce un comportamento identico per tutte le istanze della classe ossia indipendente dagli oggetti Esempio: Math.random() E un errore di sintassi per un metodo static chiamare un metodo di istanza o accedere ad una variabile di istanza

196 196 Accedere a membri static I membri static di una classe esistono indipendentemente dallesistenza di una istanza di tale classe Due tipi di accesso lNomeClasse.nomeMetodo(lista_parametri) NomeClasse.nomeVariabile lrifOggetto.nomeMetodo(lista_parametri) rifOggetto.nomeVariabile essendo rifOggetto un riferimento a un oggetto di tipo NomeClasse

197 197 La parola chiave final La parola chiave final riferita a una variabile indica che essa non può essere modificata –Sintassi: final tipo NOME = costante; –Esempio final double PI = ;

198 198 Una libreria di classi è un insieme di classi che aiuta il programmatore nello sviluppo del software. Un compilatore spesso viene distribuito con una libreria di classi fondamentali. Si possono ottenere separatamente delle librerie commerciali. Tecnicamente una libreria non fa parte della definizione del linguaggio. La libreria standard viene distribuita con qualsiasi ambiente di sviluppo. Librerie di classi

199 199 API e package Una libreria di classi è composta da gruppi di classi tra loro collegate, spesso indicate collettivamente come API (Application Programmer Interface). E possibile per esempio riferirsi al Java Database API quando si parla dellinsieme delle classi che permettono di interagire con una base di dati. Le classi della libreria standard di Java sono raggruppate in package che, come le API, permettono di indicare con un unico nome delle classi tra loro collegate. Ad esempio la classe String fa parte del package java.lang.

200 200 La clausola IMPORT Le classi del package java.lang sono automaticamente rese disponobili durante la scrittura di un programma. Se si vogliono usare le classi appartenenti ad altri package, occorre specificare il nome della classe insieme al nome del package, oppure usare la clausola import. Es.: java.util.Random import java.util.Random import java.util.*

201 201 La classe String Una stringa è una sequenza di caratteri La classe String è utilizzata per memorizzare caratteri La classe String ha metodi che consentono di operare su stringhe Costanti di tipo String : uno o più caratteri racchiusi tra doppi apici Esempi: char charVariable = `a`; // apici singoli String stringVariable = a; // doppi apici String sentence = Hello, world;

202 202 Variabili di tipo String Dichiarare una variabile di tipo String : –String greeting; Assegnare un valore alla variabile: –greeting = Hello!; Utilizzare la variabile come parametro di tipo String nella chiamata di un metodo: –System.out.println(greeting); stampa sullo schermo la stringa Hello!

203 203 Costruttori String(stringa) : –greeting = new String("Hello!"); Alloca memoria per ogni stringa anche se il parametro è lo stesso –diverso da non usare il costruttore String s = "Hello!"; String t = "Hello!"; String u = new String("Hello!"); String v = new String("Hello!"); System.out.println(s==t); // stampa true System.out.println(u==v); // stampa false

204 204 Metodi length() : ritorna la lunghezza della stringa –greeting.length() ritorna 6 toLowerCase() : ritorna la stringa con tutti caratteri minuscoli –greeting.toLowerCase() ritorna hello! toUpperCase() : ritorna la stringa con tutti caratteri maiuscoli –greeting.toUpperCase() ritorna HELLO!

205 205 Metodo charAt(int p) : ritorna il carattere nella posizione specificata »greeting.charAt(0) ritorna il carattere H mentre greeting.charAt(2) ritorna il carattere l Metodo substring(int s, int e) : ritorna la sotto-stringa dalla posizione s alla posizione e (esclusa) »greeting.substring(4,6) ritorna la stringa o! Indice di un carattere È un intero che, a partire da 0 per il primo carattere, specifica la posizione del carattere allinterno della stringa

206 206 Concatenazione di stringhe Operatore + : String name = I am Elisa; System.out.println(greeting+ +name); sullo schermo appare: Hello! I am Elisa ricordarsi di includere gli spazi per una corretta viualizzaziome

207 207 Sequenze escape Come stampare caratteri speciali? –Esempio: The word is hard System.out.println(The word is hard); –Errore di compilazione: vede la stringa The word is ed è confuso da quello che segue Usare il carattere backslash (ovvero, \ ) per indicare il significato speciale dei doppi apici interni –System.out.println(The word is \hard\); –la sequenza \ è detta essere una sequenza escape

208 208 Commenti Scrivere commenti comprensibili ed utili Non commentare ciò che è ovvio Assumere che il lettore ha una conoscenza ragionevole Tipi di commenti: –// per commenti di una singola linea –/* … */ per commenti di più linee –/** … */ per commenti che producano documentazione HTML (appendice 10)

209 209 Array Nome unico per collezione di valori tutti dello stesso tipo di dati Più di un tipo primitivo, meno di un oggetto –metodi invocati con una notazione speciale –comportamento simile ad oggetti se usati come argomenti o come tipi di ritorno –niente ereditarietà –simili ad una classe Java non completamente implementata Adatti per cicli (in particolare, cicli for )

210 210 Creazione ed accesso Sintassi generale per la dichiarazione: Tipo_Base[] Nome_Array = new Tipo_Base[Lunghezza]; Esempi: array di 80 caratteri: char[] symbol = new char[80]; array di 100 reali: double[] reading = new double[100]; array di 100 stringhe: String[] message = new String[100];

211 211 Uso delle parantesi quadre Per creare un nome di tipo –esempio: int[] intArrayName; crea un nome di tipo "array di int " tipo int diverso da tipo array di int tipo del nome intArrayName, non tipo dei dati inclusi nellarray (che comunque sono di tipo int ) Per creare un nuovo array –esempio: numArray = new int[100]; Per accedere ad uno specifico elemento dellarray –esempio: System.out.println(numArray[3]);

212 212 Terminologia temperature[n + 2] Nome temperature[n + 2] Indice - deve essere un int, - oppure un espressione che ritorna un int temperature[n + 2] Variabili indicizzata o elemento temperature[n + 2] = 32; Valore della variabile indicizzata o elemento

213 213 Lunghezza di un array Specificata dal numero dentro le parentesi quadre al momento della dichiarazione –determina la quantità di memoria allocata per gli elementi dellarray memoria allocata anche se agli elementi non è stato assegnato alcun valore –determina il massimo numero di elementi che larray può contenere Ottenuta mediante la sintassi.length String[] message = new String[20]; System.out.println(message.length); Determinata al momento della dichiarazione –non può essere modificata a meno di ridichiarare larray

214 214 Inizializzazione di array Gli elementi di un array possono essere inizializzati nellistruzione di dichiarazione mediante una lista di valori (separati da virgole) allinterno di parentesi graffe –elementi non inizializzati ricevono un valore di default (ad esempio, per array di char ) –lunghezza di array determinata automaticamente se i valori sono inizializzati esplicitamente nella dichiarazione Esempio: double[] readings = {5.1, 3.02, 9.65}; System.out.println(readings.length); -stampa 3, ovvero la lunghezza dellarray readings

215 215 Dominio di indicizzazione Indicizzazione di array usa numerazione a partire da 0 –primo elemento: indice 0 –secondo elemento: indice 1 –n-esimo elemento: indice n-1 –ultimo elemento: indice length-1 Esempio: int[] scores = {97, 86, 92, 71};

216 216 Errore di indice fuori del dominio Usare un indice più grande di length-1 causa un errore in fase di esecuzione (non di compilazione) –viene rigettata un'eccezione di tipo ArrayOutOfBoundsException Altri linguaggi di programmazione (come C e C++) non causano neanche un errore in fase di esecuzione –una delle caratteristiche più "pericolose" di questi linguaggi è proprio il fatto che consentono di usare indici fuori del dominio

217 217 Inizializzazione con ciclo Elaborazione di array facile da fare in un ciclo Ciclo for spesso usato per inizializzare un array Esempio: int[] a = new int[10]; for(int i = 0; i < a.length; i++) a[i] = 0;

218 218 Array, classi e metodi Dato array di oggetti, i metodi della classe corrispondente possono essere usati sui singoli elementi dichiara array di Rational ogni elemento è una istanza di Rational usa il metodo add della classe Rational

219 219 Array, elementi ed argomenti Array ed elementi possono essere usati come argomenti di un metodo e come tipi di ritorno –sia un elemento che un nome di array possono essere un argomento di un metodo –i metodi possono ritornare un valore di un array oppure un nome di array (incluse le parentesi quadre)

220 220 Esempio nome di array come tipo di ritorno un elemento di a è un argomento del metodo add il nome v è un argomento del metodo computeSum

221 221 Nomi di array come argomenti Quando si usa un intero array come argomento di un metodo: –si indica solo il nome dell'array senza le parentesi quadre –il metodo ha accesso all'array originale e può modificare i valori dei suoi elementi –la lunghezza dell'array passato come argomento può essere diversa ad ogni invocazione quando si definisce il metodo non si sa la lunghezza dell'array che verrà passato –utilizzare length all'interno del metodo per evitare una eccezione di tipo ArrayIndexOutOfBoundsException

222 222 Esempio Rational computeSum(Rational[] a) { if (a.length==0) return null; Rational tot = a[0]; for (int i=1; i

223 223 Array ed operatore = int[] a = new int[3]; int[] b = new int[3]; for(int i; i < a.length; i++) a[i] = i; b = a; System.out.println(a[2] + " " + b[2]); a[2] = 10; System.out.println(a[2] + " " + b[2]); Non crea una copia dell'array a ma trasforma b in un altro nome per l'array a Output: 2 10 Un valore cambiato in a è lo stesso valore ottenuto con b

224 224 Array ed operatore == int i; int[] a = new int[3]; int[] b = new int[3]; for(i=0;i

225 225 Uguaglianza tra array Per verificare se due array sono uguali bisogna definire un metodo equals che ritorna il valore true se e solo se gli array hanno la stessa lunghezza e tutti gli elementi corrispondenti sono uguali

226 226 Metodi che ritornano un array Un altro esempio di passaggio per riferimento In pratica, non viene restituito l'array, ma il suo indirizzo Il nome della variabile a cui l'array viene assegnato è semplicemente un altro nome per l'array ritornato dal metodo

227 227 Buone regole di programmazione Usare nomi singolari piuttosto che plurali migliora la leggibilità –sebbene un array contenga molti elementi, l'uso più frequente del suo nome sarà per indicizzare un singolo elemento Non affidarsi ai valori iniziali di default per gli elementi di un array –inizializzare esplicitamente gli elementi nella dichiarazione oppure in un ciclo

228 228 Ricerca in un array Esistono molte tecniche per cercare un particolare valore all'interno di un array Ricerca sequenziale: –partire dall'inizio dell'array e procedere in sequenza finché il valore viene trovato oppure la fine dell'array viene raggiunta oppure, partire dalla fine dell'array e procedere a ritroso finché il valore viene trovato oppure l'inizio dell'array viene raggiunto –non è il modo più efficiente, ma funziona ed è facile da programmare

229 229 Esempio public boolean inArray(int[] a, int x) { boolean found = false; int i = 0; while ((! found) && (i

230 230 Ordinare un array Ordinare un elenco di elementi è un compito molto frequente –ordinare numeri in modo crescente –ordinare numeri in modo decrescente –ordinare stringhe in modo alfabetico Vi sono molti modi per ordinare un elenco Selection sort –uno dei più facili –non il più efficiente, ma facile da capire e da programmare

231 231 Algoritmo Selection Sort Per ordinare un array di interi in modo crescente: –cerca nell'array il numero più piccolo e scambialo con il primo elemento dell'array la parte ordinata dell'array è ora il primo elemento, mentre quella non ancora ordinata sono i rimanenti elementi –cerca nella parte non ordinata il numero più piccolo e scambialo con il secondo elemento dell'array –ripeti la ricerca e lo scambio fino a quando tutti gli elementi sono al posto giusto ogni iterazione aumenta di 1 la lunghezza della parte ordinata e diminuisce di 1 quella della parte non ordinata

232 232 Il codice public void selectionSort(int[] a) { int i, j, indexOfNextSmallest, min, temp; for (i = 0; i < a.length - 1; i++) { min = a[i]; indexOfNextSmallest = i; for (j = i+1; j < a.length; j++) if (a[j] < min) { min = a[j]; indexOfNextSmallest = j; } temp = a[i]; a[i] = a[indexOfNextSmallest]; a[indexOfNextSmallest] = temp; }

233 233 Esempio

234 234 Il metodo main Il parametro formale di un metodo main è sempre un array di oggetti di tipo String. La macchina virtuale java invoca il metodo main nellapplicazione che viene passata allinterprete Il parametro di tipo array di stringhe, che solitamente viene chiamato args, rappresenta linsieme di argomenti passati tramite la linea di comando allinterprete Java quando viene invocato.

235 235 Qualsiasi informazione passata dalla linea di comando viene memorizzata nellarray args per poter essere successivamente usata dal programma. Il parametro del metodo main è sempre un array di oggetti di tipo String, per cui se si ha bisogno di passare dalla riga di comando informazioni in altro formato, ad esempio numerico, il programma dovrà convertirle in formato stringa.

236 236 Complessità computazionale Per risolvere un problema spesso sono disponibili molti algoritmi diversi. Come scegliere il migliore? In genere si valuta la bontà di un algoritmo o si confrontano più algoritmi sulla base del comportamento che questi presentano al crescere della dimensione del problema.

237 237 Si vuole caratterizzare tale dimensione mediante un intero n che è precisamente identificato nella macchina di Turing come la lunghezza della porzione di nastro che contiene i dati di ingresso. Impiegando un elaboratore ed un suo linguaggio di programmazione, la dimensione n è lo spazio occupato, nella memoria dellelaboratore, dei dati relativi al problema da risolvere, o più in generale un numero proporzionale a questo spazio.

238 238 Esempi: se si opera su un insieme, n sarà il numero dei suoi elementi se si opera su un grafo, n sarà il numero dei nodi o il numero di archi o la somma dei due numeri se si opera su matrici n sarà il numero dei suoi elementi

239 239 Fissata la dimensione n, il tempo che un algoritmo impiega a risolvere il problema si chiama complessità in tempo: nostro obiettivo principale sarà esprimere la complessità in tempo come funzione di n e spesso ci limiteremo a studiare il comportamento di tale funzione al crescere di n (complessità asintotica o semplicemente complessità) considerando così i soli termini prevalenti per e tralasciando a volte anche le costanti moltiplicative. Complessità in tempo e complessità asintotica

240 240 Lo studio della complessità asintotica è motivato dal fatto che gli algoritmi sono sempre definiti per n generico: se per valori piccoli di n due algoritmi possono avere efficienza confrontabile, è sempre quello che ha il termine massimo di grado più basso a richiedere minor tempo di esecuzione per un numero illimitato di valori di n superiori ad un opportuno valore n 0. Perché si studia la complessità asintotica

241 241 ATTENZIONE!!! Non saremo mai in grado di valutare il tempo effettivamente impiegato da un algoritmo, si dovrebbe mettere in bilancio il tempo di esecuzione delle singole frasi su uno specifico elaboratore.

242 242 Quello che faremo Ci limiteremo a contare le operazioni eseguite o alcune operazioni chiave o preminenti ammettendo che il tempo complessivo di esecuzione sia proporzionale al numero di tali operazioni. Tratteremo spesso come non significative le costanti moltiplicative e studieremo le funzioni di complessità nel loro ordine di grandezza.

243 243 La complessità in spazio è il massimo spazio invaso dalla memoria durante lesecuzione dellalgoritmo, il quale può costruire insiemi di dati intermedi o di servizio, oltre ad operare sui dati iniziali e finali. Anche in questo caso ci si limita in genere allo studio della complessità asintotica. Poiché abbiamo a disposizione memorie grandissime a basso costo, studieremo la complessità in tempo. Complessità in spazio

244 244 Complessità e configurazioni La complessità di un algoritmo non può sempre essere caratterizzata da una sola funzione di complessità. A parità di dimensione di dati, il tempo di esecuzione può dipendere dalla specifica configurazione dei dati. Si considerano di solito tre differenti tipi di complessità: complessità nel caso medio, ottimo e pessimo.

245 245 Complessità media Valore della complessità di un algoritmo, mediato su tutte le possibili occorrenze iniziali dei dati. Si usa spesso la probabilità. Il calcolo è spesso difficile.

246 246 Complessità nel caso ottimo Si ottiene considerando, a parità di dimensione dei dati, la configurazione che dà luogo alminimo tempo di esecuzione. Tale complessità è perlopiù di interesse secondario anche se è abbastanza facile da determinare.

247 247 Complessità nel caso pessimo Si intende la complessità relativa a quella particolare occorrenza iniziale dei dati per cui lalgoritmo ha comportamento pessimo. Tale funzione di complessità fornisce un limite superiore alla complessità, entro cui il funzionamento dellalgoritmo è sempre garantito.

248 248 Crescita asintotica della complessità Le funzioni considerate rappresentano tempi di elaborazione e spazi di memoria e sono intrinsecamente non negative ( ed in genere crescenti con la dimensione dei dati n che è un intero non negativo). In genere ci interesseremo al limite della funzione complessità quando n (studio della complessità in ORDINE DI GRANDEZZA).

249 249 Notazioni g(n) O(f(n)) tradizionalmente si legge g(n) è di ordine f(n) e fornisce un limite superiore al comportamento asintotico della funzione. O(f(n)) è linsieme di tutte le funzioni g(n) tali che esistono due costanti positive c e n 0 per cui g(n) = n 0

250 250 (f(n)) è linsieme di tutte le funzioni g(n) tali che esistono due costanti positive c e n 0 per cui g(n)>=cf(n) per ogni n>= n 0. g(n) (f(n)) tradizionalmente si legge g(n) è di ordine f(n) e fornisce un limite inferiore al comportamento asintotico della funzione.

251 251 (f(n)) è linsieme di tutte le funzioni g(n) che sono sia f(n) sia Of(n). g(n) (f(n)) tradizionalmente si legge g(n) è di ordine f(n); la g si comporta asintoticamente esattamente come la f, per cui landamento di f caratterizza precisamente quello di g.

252 252 Applicata alla funzione di complessità, la notazione O ne delimita superiormente la crescita e fornisce un indicatore di bontà dellalgoritmo. La notazione limita inferiormente la complessità, indicando così che il comportamento dellalgoritmo non è migliore di un comportamento assegnato.

253 253 Esempi: la funzione h(n)=3n 2 +3n-1 è di ordine n 2 perché esistono le costanti c=4 e n 0 =3 per cui h(n) =3. Notiamo che qualsiasi polinomio di grado k è di ordine n k e,in accordo con la definizione, è anche di ordine n j con j>k.

254 254 g(n)=3n 2 +2n+1 è O(n 2 ) e anche O(n 3 ) ma è anche di ordine (4n 2 ), (n 2 ), (n); Infine è di ordine (n 2 ), (4n 2 ), ma non di ordine (n) e neppure di ordine (n 3 )

255 255 Proprietà di O, e g O(f) implica (f+g) O(f) f 1 O(g 1 ), f 2 O(g 2 ) implica f 1 + f 2 O(g 1 +g 2 ) O e sono relazioni riflessive e transitive è una relazione di equivalenza f O(g) se e solo se g (f)

256 256 Possiamo dividere ora gli algoritmi in classi, ponendo nella stessa classe quelli che hanno complessità asintotica dello stesso ordine di grandezza O.

257 257 Classi principali funzioni di ordine costante di ordine inferiori ad n, o sottolineari di ordine nlogn (la base del logaritmo è inessenziale perch é logaritmi in basi diverse differiscono per una costante moltiplicativa: log a y=log a b x log b y) di ordine n 2,n 3 ecc., o in genere polinomiali di ordine k n,n n..o in genere esponenziali

258 258 Un esempio:Ordinare un array Ordinare un elenco di elementi è un compito molto frequente –ordinare numeri in modo crescente –ordinare numeri in modo decrescente –ordinare stringhe in modo alfabetico Vi sono molti modi per ordinare un elenco Selection sort –uno dei più facili –non il più efficiente, ma facile da capire e da programmare

259 259 Algoritmo Selection Sort Per ordinare un array di interi in modo crescente: –cerca nell'array il numero più piccolo e scambialo con il primo elemento dell'array la parte ordinata dell'array è ora il primo elemento, mentre quella non ancora ordinata sono i rimanenti elementi –cerca nella parte non ordinata il numero più piccolo e scambialo con il secondo elemento dell'array –ripeti la ricerca e lo scambio fino a quando tutti gli elementi sono al posto giusto ogni iterazione aumenta di 1 la lunghezza della parte ordinata e diminuisce di 1 quella della parte non ordinata

260 260 Il codice public void selectionSort(int[] a) { int i, j, indexOfNextSmallest, min, temp; for (i = 0; i < a.length - 1; i++) { min = a[i]; indexOfNextSmallest = i; for (j = i+1; j < a.length; j++) if (a[j] < min) { min = a[j]; indexOfNextSmallest = j; } temp = a[i]; a[i] = a[indexOfNextSmallest]; a[indexOfNextSmallest] = temp; }

261 261 Esempio

262 262 Complessità del Selection sort Lordinamento per selezione ha un ciclo più esterno e uno più interno con proprietà simili, sebbene con scopi differenti. Il ciclo più esterno viene eseguito una volta per ogni valore nella lista e quello più interno confronta il valore scelto dal ciclo più esterno con molti, se non tutti, i valori rimanenti nella lista. Quindi esegue n 2 confronti ove n è il valore di elementi della lista. Selection sort è quindi di ordine n 2.

263 263 Secondo lo stile ricorsivo un programma risolve un problema facendo ricorso a chiamate dello stesso programma che risolvono un problema sui dati originali opportunatamente ridotti. I risultati ottenuti con le singole chiamate vengono poi combinati per ottenere il risultato finale. Programmi ricorsivi

264 264 E responsabilità di chi formula lalgoritmo porvi in posizione opportuna la clausola di chiusura per assicurarsi che le chiamate successive della procedura abbiano termine. E responsabilità del sistema di elaborazione organizzare i calcoli richiesti dalla procedura che devono essere eseguiti aggregando man mano dati elementari.

265 265 Ogni parametro di una procedura ricorsiva può assumere allo stesso tempo valori indipendenti. Il valore impiegato in unesecuzione muore con il completamento di questa ed è sostituito dal valore relativo allultima esecuzione lasciato in sospeso. Tali assegnazioni come i problemi lasciati in sospeso sono i problemi dellelaboratore.

266 266 Il programmatore formula lalgoritmo dal generale al particolare descrivendo la funzione sulla globalità dei dati in termini della funzione stessa sui dati disgregati. Lalgoritmo viene poi eseguito dal particolare al generale. Vengono infatti lasciate in sospeso le operazioni globali e il calcolo vero e proprio inizia dai dati atomici.

267 267 Possiamo pensare alle operazioni effettuate prima e dopo le chiamate ricorsive come ad un LAVORO DI COMBINAZIONE dei risultati parziali in cui si fa confluire leventuale lavoro di preparazione dei dati per le chiamate ricorsive stesse.

268 268 Quando un algoritmo è scritto in maniera ricorsiva può risultare relativamente facile caratterizzare in modo compatto e semplice le funzioni di complessità. Le relazioni di ricorrenza nascono infatti quando un elemento generico di una sequenza può essere espresso in funzione dei termini precedenti. Si usa classificare le più importanti relazioni di ricorrenza anche in base alla forma del lavoro di combinazione. RELAZIONI DI RICORRENZA

269 269 Fibonacci Una delle prime relazioni di ricorrenza fu posta da Fibonacci. Problema dei conigli: Al tempo 1, origine dei tempi, cè una coppiua di conigli neonati. Al tempo successivo la coppia diventata adulta, inizia il processo di riproduzione: ogni coppia genera una nuova coppia ogni mese, ma ogni nuova coppia non è in grado di procreare durante il primo mese. Quante coppie vi sono al mese n? Il numero cercato è ln-esimo numero di Fibonacci.

270 270 F 3 =2 la prima coppia procrea una seconda al mese n vi sono le coppie del mese precedente, F n-1, pi ù quelle generate nell ultimo mese che sono quelle esistenti nel mese ancora precedente, F n-2. F 1 =1 al mese 1 cè solo una coppia F 2 =1 al mese 2 ancora la prima coppia non può procreare Condizioni iniziali F n =F n-1 +F n-2 Relazione di ricorrenza

271 271 Cerchiamo di esprimere F n in funzione di n, cercando quindi una soluzione per la relazione di ricorrenza. La legge generale conterrà delle costanti da determinare imponendo delle condizioni iniziali. Ipotizziamo che ci sia una soluzione del tipo F n =cz n dove c e z sono costanti.

272 272 Sostituiamo in F n =F n-1 +F n-2 la soluzione ipotizzata.

273 273 Possiamo quindi affermare che cz n è una soluzione della relazione di ricorrenza in uno dei seguenti tre casi:

274 274 Quindi F n ammette le due soluzioni F n =c 1 z 1 n F n =c 2 z 2 n Purtroppo non generano tutti i numeri di Fibonacci al variare di n dato che nessuna delle due è in grado di soddisfare le due condizioni iniziali. In virtù della linearità di F n =F n-1 +F n-2 una combinazione lineare delle due soluzioni è ancora una soluzione della relazione. In particolare consideriamo: F n = c 1 z 1 n +c 2 z 2 n

275 275 Imponendo le condizioni iniziali:

276 276 Si ottiene quindi:

277 277

278 278

279 279

280 280

281 281

282 282 Soluzioni

283 283 Esempio: PRIMSEC algoritmo ricorsivo che determina il primo e il secondo elemento di un insieme secondo un ordine assegnato. Sia A un vettore di n elementi distinti con un ordine prefissato. Si divide in due metà il vettore e si applica ricorsivamente lalgoritmo fino a che non si arriva a due coppie alle quali si applica il confronto.

284 284 Sotto lipotesi che n=2 h i due insiemi iniziali si dividovo esattamente in due ad ogni passo finch é dopo h-1 suddivisioni si ottengono insiemi elementari di due elementi. Valutiamo il numero di confronti eseguiti per calcolare la funzione di complessit à. Avremo che: C(n)=1 per n=2 C(n)=2C(n/2)+2 per n>2 Questo modo di impostare l algoritmo si chiama DIVIDE ET IMPERA (prossima lezione)

285 285 Non abbiamo il numero esatto dei confronti ma abbiamo lordine di grandezza della nostra funzione di complessità che essendo nel caso c) con a>1 risulta essere

286 286 Soluzione di c) per sostituzioni successive

287 287

288 288

289 289

290 290

291 291 Se a


292 292 Se a=p la funzione di complessità è LINEARE. Ed infine se a>p la funzione è SOPRALINEARE anche se non cresce in genere come un polinomio di grado elevato a causa della funzione logaritmica che appare allesponente. Ciò avviene quando si deve operare più volte sugli stessi dati. Es: se a=3 e b=2 si avrà bisogno di tre chiamate su sottoinsiemi di n/2 dati e cioè sovrapposizione.

293 293 Algoritmi di ordinamento Problema: Sia A un array di n elementi tra i quali é definita una relazione di ordine totale <. Si vuole permutare tali elementi in maniera tale che risulti : A[1]< A[2]<……< A[n] Dove con A[i] indichiamo il valore dellennesimo elemento dellarray.A.

294 294 QUICKSORT Algoritmo: si sceglie a caso un elemento detto perno A[h]. si confronta con A[h] tutti gli altri elementi di A e si costruiscono due insiemi A 1 e A 2 tali che: A 1 ={x/x A e x< A[h]} A 2 ={x/x A e x> A[h]} si trasferiscono gli elementi di A 1 all inizio dell array, seguiti dal perno, seguiti dagli elementi di A 2. Si ripete ricorsivamente quicksort.

295 295 Esempio: A[1]=30 A[2]=40 A[3]=25 A[4]=50 A[5]=15 A[6]=45 A[7]=38 A[8]=5 A[9]=10 A[10]=35. Se la distribuzione iniziale è casuale posso scegliere come perno anche A[1]. Si scorrerà larray A dal secondo elemento con due cursori p e q: p punterà inizialmente ad A[2] e si sposterà verso destra; q punterà ad A[n] ( nellesempio A[10]) e si sposterà verso sinistra. Il movimento dei cursori si arresta non appena: A[1] A[q] A questo punto si scambiano di posto A[p] e A[q] e si riprende il moto dei cursori, iterando il procedimento finché i cursori si incontrano in posizione intermedia.

296 296 Si scambia allora di posto A[1] con lelemento minore più a destra ottenendo così una permutazione di A in cui si trovano allinizio gli elementi minori del perno, quindi il perno e infine tutti gli elementi maggiori del perno. I sottoinsiemi: A 1 ={15, 10, 25, 5} A 2 ={45,38,50,40,35} Saranno trattati ricorsivamente nello stesso modo.

297 297 Evoluzione dellarray A durante le partizioni intorno al perno

298 298 Codice per Quicksort public static void quicksort(int[] A) { quicksort (A,0,A.lenght-1);} public static void quicksort(int[] A, int i, int j) { if (i >=j)return; int p= perno(A,i,j); if (i <(p-1)) quicksort(A,i,p-1); if ((p+1)

299 299 while ((p

300 300 Lalgoritmo, scritto qui con sintassi java, ha un metodo perno non ricorsivo. E chiamato su un array di interi A partiziona le parti comprese tra i e j attorno al perno generico A[i]. I due cursori sono p e q e partono appunto dalle posizioni i+1 e j (nellesempio A[2] e A[10]). Il metodo perno restituisce la posizione del perno. Il metodo quicksort(A,i,j) richiama perno ricorsivamente provocando lordinamento dellarray tra i e j. Il metodo quicksort(A) provoca lordinamento dellintero array.

301 301 Relazione di ricorrenza per il Quicksort Complessità di perno Complessità su A 1 Complessità su A 2

302 302 Analizzando il metodo perno ci accorgiamo che il ciclo esterno si ferma quando p>q cioè p=q+1 cioè quando A[p] è lelemento più a sinistra maggiore del perno e A[q] è lelemento più a destra minore del perno. Ciò significa che tutti gli elementi (n-1 elementi se non contiamo il perno) vengono confrontati 1 volta sola con il perno tranne A[p] e A[q] che sono in genere confrontati 2 volte con li perno. Abbiamo quindi:

303 303 Caso medio per Quicksort Dato che il valore j prodotto dal metodo perno può essere con la stessa probabilità 1/n in ciascuna posizione tra 1 e n abbiamo per il caso medio:

304 304 Tale relazione dopo una serie di calcoli che saranno svolti a lezione e che potete trovare nel libro Algoritmi e strutture dati di Fabrizio Luccio diventa la seguente funzione esplicita in n : Lalgoritmo quindi stabilisce una relazione di ordinamento tra moltissime coppie senza confrontarle direttamente ma inferendo tale relazione da confronti fatti con altri elementi. Infatti se si eseguissero tutti i possibili confronti tra coppie di elementi si avrebbe C M (n)=n(n-1)/2 cioè quante sono le coppie distinte di n elementi,

305 305 Il comportamento medio di tale algoritmo si avvantaggia del fatto che le successive partizioni di dati sono mediamente bilanciate. Supponiamo infatti che lelemento perno abbia il valore centrale di A. Il metodo perno mette il perno al centro e costruisce i due insiemi A 1 e A 2 di dimensione metà dellinsieme originale: il metodo corre perfettamente secondo partizioni bilanciate dellinsieme. Si eseguono n+1 confronti per tutte le chiamate di perno ad ogni livello di ricorrenza, ma tali livelli sono meno quando le successive partizioni dellinsieme sono perfettamente bilanciate! Ecco che nel caso ottimo il perno ha il valore centrale e C(n) é dellordine nlogn.

306 306 Caso pessimo Quicksort In questo caso il perno è sullelemento che risulta il minimo ( o il massimo) degli elementi di A. In questo caso si ha che A 1 è vuoto mentre A 2 contiene n-1 elementi. Abbiamo quindi:

307 307 Nel caso pessimo quindi il numero dei confronti ha un numero assai maggiore che nel caso medio, questo dipende dal completo sbilanciamento della partizione di A, che obbliga essenzialmente ad eseguire tutti i possibili confronti tra coppie di elementi. Da osservare che Quicksort opera con massima inefficienza quando linsieme è già ordinato.

308 308 MERGESORT Non abbiamo comunque individuato un metodo di ordinamento che operi O(nlogn) confronti anche nel caso pessimo (il limite inferiore al numero di confronti generato con lalbero di decisione è O(nlogn) sia nel caso medio che nel caso pessimo); la possibilità di raggiungere questo risultato appare legato alla costruzione di un algoritmo che lavori su partizione dellinsieme bilanciate in ogni caso: il Mergesort.

309 309 Il Mergesort, chiamato anche metodo di ordinamento per fusione, si basa sullidea di dividere linsieme da ordinare A (o meglio larray nel nostro codice) di n elementi in due sottoinsiemi di n/2 elementi ciascuno, ordinare poi ciascuna sequenza e fondere insieme le due unità ordinate in ununica sequenza. In realtà nella versione ricorsiva qui presentata Mergesort si applica allintero array e ne costruisce lordinamento mediante la fusione di due semi-insiemi ordinati ricorsivamente nello stesso modo. Nel Mergesort le chiamate ricorsive si susseguono luna dentro laltra finchè si raggiungono insiemi elementari di due elementi su cui iniziare le vere e proprie operazioni di confronto e ordinamento, con la fusione di due sottoinsiemi di un elemento ciascuno (procedura Merge non ricorsiva). Da qui si passa via via alla fusione di sottoinsiemi più grandi: le operazioni iniziano sempre su dati elementari.

310 310 Codice per Mergesort public static void mergesort(int[] A) { aus=new int[A.lenght] mergesort(A,0,A.lenght-1);} public static void mergesort(int[] A, int i, int j) { if (i >=j)return; int m= (i+j)/2; mergesort(A,i,m); mergesort(A,m+1,j); merge(A,i,j,m) }

311 311 public static void merge(int[] A, int i, int j,int m) { int p=i; int q=m+1; int k=i; while ((p<=m) && (q<=j)) { if (A[p]=k;k1--) {A[k1]=A[p];p--;}} for(int k1=i;k1

312 312 Numero di confronti richiesto dal Merge Studio della complessità per il Mergesort

313 313 Mergesort è un algoritmo ottimo anche nel caso pessimo: il motivo è ancora da ricercarsi nel fatto che la partizione operata da Mergesort è sempre bilanciata!


Scaricare ppt "1 Master in BIOINFORMATICA Corso propedeutico di Informatica DOCENTE: Elisa Tiezzi UNIVERSITA DI SIENA."

Presentazioni simili


Annunci Google