Fabrizio Messina, Marzio Pennisi {messina,

Fabrizio Messina, Marzio Pennisi {messina,mpennisi}@dmi.unict.it
Argomenti trattati
Algoritmo: definizione
Analisi e programmazione: attività preliminari atte a risolvere
problemi utilizzando un elaboratore, dalla formulazione del
problema fino alla predisposizione dell’elaboratore.
ALGORITMO: un elenco finito di istruzioni che specificano una serie
di operazioni, eseguendo le quali è possibile risolvere ogni problema di un
dato tipo (classe di problemi).
Un algoritmo può essere utilizzato per risolvere un particolare problema.
● In questo caso l'uomo può eseguire le istruzioni indicate nell'algoritmo
sui dati che caratterizzano il particolare problema da risolvere.
● Un algoritmo non può essere eseguito direttamente
da un elaboratore.
Programma: definizione
• Scopo della programmazione è quello di definire
un programma.
• Un programma è la descrizione di cosa deve fare
un elaboratore (insieme univoco di istruzioni) per
risolvere ogni problema di un dato tipo.
• Programma -> descrizione di un algoritmo in una
forma “comprensibile” per l’elaboratore.
Linguaggio di programmazione: definizione
• Un linguaggio di programmazione è rappresentato da un insieme di
regole formali per la stesura di un programma comprensibile per un
calcolatore.
• Tramite un linguaggio di programmazione, è possibile descrivere un
algoritmo in modo che esso diventi un programma.
• La soluzione di un particolare problema di un dato tipo si ottiene
eseguendo il programma formulato per la soluzione di quel tipo
di problemi e specificando i dati caratteristici del problema
particolare.
• I risultati ottenuti dalla esecuzione del programma rappresentano la
soluzione richiesta.
• L’esecuzione di un programma è anche detta elaborazione.
Analogie tra uomo ed elaboratore
Analisi e programmazione
Primi esempi di algoritmo
• Esempio: Ordinamento di un mazzo di 40 carte
• Problema: Si supponga di avere un mazzo da 40 carte mescolato. Si vuole ordinare il
mazzo di carte in modo che le carte con il seme cuori siano poste per prime, seguite
dalle carte con seme quadri, fiori e picche. Le carte di uno stesso seme sono ordinate
dall'asso al re.
• Algoritmo (possibile):
1. inizio dell’algoritmo;
2. Suddividere il mazzo in 4 mazzetti; ciascun mazzetto è costituito da tutte le carte
dello stesso
seme;
3. Ordinare le carte di ciascun mazzetto dall’asso al re;
4. Prendere nell’ordine il mazzetto dei cuori, dei quadri, dei fiori e delle picche;
5. fine dell'algoritmo.
Primi esempi di algoritmo (segue)
• Esempio: Calcolo delle radici delle equazioni di secondo grado.
• Problema: Determinare le radici x1, x2, dell’equazione di secondo grado ax2 +bx+ c=0. Il
procedimento prevede il calcolo del determinante Δ =b2 - 4ac. Se Δ > 0 si hanno due radici reali e
distinte x1 e x2 = [-b ± √(Δ) ] /2a. Se Δ = 0 si hanno due radici reali coincidenti x1 e x2 = -b/2a. Se Δ<
0 non si hanno radici nel campo dei numeri reali.
• Algoritmo (possibile):
1. inizio dell’algoritmo;
2. Introdurre i valori di a, b e c;
3. Calcolare Δ =b2 - 4ac;
4. Se Δ > 0 porre x1=[-b + √(Δ) ] /2a e x2=[-b - √(Δ) ] /2a e poi passare all’istruzione 7;
5. Se Δ = 0 porre x1=x2= -b /2a e poi passare all’istruzione 7;
6. Se Δ < 0 restituire il messaggio “non esistono radici reali” e poi passare all’istruzione 8;
7. Restituire x1 e x2;
8. Fine dell’algoritmo.
Algoritmo: istruzioni e dati
Fino ad adesso sono state utilizzate delle proposizioni per descrivere un algoritmo.
Le proposizioni sono composte di due parti:
• Operazioni da eseguire (ISTRUZIONI)
• Oggetti sui quali eseguire le operazioni al fine di ottenere i risultati (DATI).
Esempi sugli algoritmi appena visti:
ISTRUZIONI
DATI
calcola b2 - 4ac
porre….x1=x2
suddividere in quattro mazzetti
4, a, b, c,
x1 e x2
mazzo di carte
I DATI: Costanti e variabili
Gli oggetti (dati) sui quali si opera per mezzo di un algoritmo sono solitamente
di 2 tipi:
Costante: tipo di dato che rimane invariato durante l’esecuzione dell’algoritmo.
Variabile: Una variabile si può definire come una coppia <nome,valore>. Essa
si può paragonare ad un contenitore con un’etichetta. Questa scatola conterrà, in
generale, differenti valori durante l’esecuzione dell’algoritmo.
valore
nome
Costanti e variabili
• Data una variabile <x,v> si dice che x è il nome della variabile e che v è il
valore attuale della variabile di nome x (oppure, più semplicemente, che v è il
valore di x).
• Un dato variabile risulta indeterminato al momento della definizione
dell'algoritmo;
• il dato però corrisponde a un valore ben preciso durante ogni esecuzione dell’
algoritmo.
• Esempio: Radici di una equazione di 2° grado.
• Si consideri il passo 3 "Δ =b2 - 4ac" i dati a, b, c non corrispondono a nessun
valore finché non si esegue l'algoritmo per una ben precisa equazione di 2°grado,
ad esempio x2 - 9x - 4 = 0.
• Solo durante l’esecuzione dell’algoritmo (in particolare al passo 2) è possibile stabilire
che i nomi a, b, c corrispondono, rispettivamente, ai numeri 1; - 9; - 4!
L’istruzione di assegnamento
L’istruzione di assegnamento (assegnazione) permette di definire il valore attuale v di
una variabile x.
Quel valore resta inalterato finché una successiva assegnazione non modifica il
valore stesso.
L'assegnazione si può rappresentare con la seguente istruzione:
x ← espressione
e si legge: assegna a x il valore di “espressione”.
L'espressione a destra di ← sarà un’opportuna espressione che include l’uso di costanti,
nomi di variabili e/o simboli di operazione.
Assegnazione (segue)
Ad esempio,se abbiamo
b
c
dopo l’operazione di assegnazione a ← b + c
6
a
b
c
Utilità delle assegnazioni
Gli algoritmi si possono descrivere in modo conciso utilizzando variabili e assegnazioni.
Ad esempio, una operazione come "calcolare il volume di un parallelepipedo per mezzo
del prodotto dei valori delle tre dimensioni" può essere espressa come:
volume ← lunghezza X larghezza X altezza
I nomi delle variabili sono arbitrari;
È di solito opportuno scegliere il nome di una variabile in modo che ricordi il significato del
valore associato.
In un algoritmo è sempre necessario rispettare la regola dell’ordinamento:
•
Se una variabile compare a destra di una operazione di assegnazione è necessario che a
quella variabile sia stato precedentemente associato un valore.
Algoritmo: Tipi di “istruzione”
a. istruzioni operative: istruzioni che effettivamente producono dei risultati, se
eseguite (e.g. istruzioni di assegnamento).
b. istruzioni di controllo: istruzioni che controllano il verificarsi o meno di
condizioni specificate.
○ In base al risultato del controllo determinano l’esecuzione di alcune istruzioni
anziché altre.
c. Istruzioni di salto: istruzioni che alterano il normale ordine di esecuzione dell’
algoritmo, specificando esplicitamente quale sia la successiva istruzione da
eseguire.
○ Salto condizionato: l'effettiva esecuzione del salto sia vincolata al verificarsi
di una condizione specificata (include al suo interno una istruzione di
controllo).
○ Salto incondizionato: che il salto viene eseguito tutte le volte che
l'istruzione è eseguita;
Algoritmo: tipi di “istruzione” (segue)
d. inizio esecuzione: indica l’inizio dell’esecuzione dell'algoritmo;
e. fine esecuzione: indica la fine dell'esecuzione dell'algoritmo;
f. I/O (o trasmissione): indica come la trasmissione di dati o messaggi debba avvenire
tra l’algoritmo e l’ambiente esterno.
Possono essere:
• di ingresso o input (di lettura): i valori vengono trasmessi da un ambiente
esterno all'interno dell'algoritmo oppure istruzioni
• di uscita o output (di scrittura): i valori debbono essere trasmessi dall'algoritmo
verso l'ambiente esterno.
Esempio tipo di ''istruzione''
(algoritmo radici equazione secondo grado)
Istruzione di inizio esecuzione
1. Inizio dell’algoritmo;
Istruzioni di
controllo
2. Introdurre i valori di a, b e c;
Istruzione di input
3. Calcolare Δ ← b2 - 4ac;
Istruzione operativa
4. Se Δ > 0 porre x1 ←[-b + √(Δ) ] /2a e x2 ←[-b - √(Δ) ] /2a e poi passare all’istruzione 7;
5. Se Δ = 0 porre x1 ← x2 ← -b /2a e poi passare all’istruzione 7; Istruzione di salto
6. Se Δ < 0 restituire il messaggio “non esistono radici reali” e poi passare all’istruzione 8;
Istruzione di salto
7. Restituire x1 e x2;
8. Fine dell’algoritmo.
Istruzione di output
Istruzione di fine esecuzione
Proposizioni e predicati
Una proposizione è un costrutto
di verità). Ad esempio:
linguistico del quale si può dire se è vero o falso (valore
Roma è la capitale della Francia;
3 è un numero intero;
1 è un numero dispari;
Viceversa
le
seguenti non
sono proporzioni
Luigi, leggi quel libro!
arrivederci a tutti.
Una proposizione è un predicato se in essa appaiono delle variabili, e il valore di
tali variabili determina il valore di verità della proposizione stessa.
Esempio:
la variabile età è minore di 30;
la variabile base ha un valore maggiore di quello della variabile altezza
Valutazione di un predicato
Valutazione del predicato. Operazione che permette di determinare se il predicato è vero o falso s
sostituendo alle variabili i loro valori attuali.
●
i due valori vero e falso si dicono valori logici o booleani.
età < 30
base > altezza
Per la scrittura dei predicati è possibile utilizzare i seguenti simboli, detti operatori relazionali
oppure operatori di confronto:
=
uguale
>
maggiore
≥ maggiore o
uguale
≠ diverso
<
minore
≤ minore o uguale
I predicati che contengono un solo operatore relazionale sono detti predicati
semplici.
Predicati composti
È inoltre possibile utilizzare all’interno di un predicato i seguenti operatori booleani:
• AND (indicato anche con ^ )
• OR ( indicato anche con v )
• NOT (indicato anche con il simbolo di soprasegnato)
I predicati nei quali compare almeno un simbolo NOT, AND, OR sono detti predicati composti.
La tavola di verità di un predicato composto è un modo di descrivere il significato un predicato.
Essa consiste nello specificare il valore del predicato per ognuna delle possibili combinazioni degli
argomenti del predicato.
Le tavole di verità dei predicati p AND q e p OR q sono le seguenti:
p AND q
p
q
p OR q
p
q
vero
vero
vero
vero
vero
vero
falso
falso
falso
vero
falso
falso
falso
vero
falso
vero
vero
falso
vero
falso
falso
falso
vero
falso
Costruzione di algoritmi mediante analisi
Un algoritmo si ottiene come risultato di un procedimento di analisi che può essere
suddiviso in tre fasi:
a) definizione del problema: non si deve riferire ad un caso
concreto, ma casi generali.
b) scelta del metodo di soluzione: si definisce il metodo da
seguire per risolvere il problema;
c) descrizione delle operazioni o sviluppo dell’algoritmo: una
volta scelto il metodo si descrivono le operazioni che devono
essere eseguite per risolvere il problema scelto.
Costruzione di algoritmi mediante analisi: metodo delle
decomposizioni successive.
1.
2.
3.
4.
Definizione del problema.
Scomposizione del problema in sottoproblemi.
Per ognuno dei sottoproblemi si sceglie il metodo di soluzione.
Fornire una descrizione dettagliata di ciascun sottoproblema, in modo da
ottenere una così successive scomposizioni del problema, fino ad ottenere una
scomposizione finale, che contenga solo descrizioni di operazioni
direttamente eseguibili.
5. La successione di operazioni direttamente eseguibili è l’algoritmo.
Nei problemi particolarmente semplici, la prima scomposizione è sufficiente
a trovare per la definizione dell’algoritmo.
Il metodo delle scomposizioni successive risulta particolarmente utile
quando i problemi da risolvere sono complicati. Gli esempi successivi sono
introdotti soprattutto a scopo illustrativo.
Costruzione di algoritmi mediante analisi (segue)
Esempio: Calcolare la somma delle prime n potenze del 2. È noto che:
Pertanto questa notazione algebrica fornisce il metodo per la soluzione del problema posto. In
questo caso la scelta del metodo coincide con la descrizione delle operazioni direttamente
eseguibili.
L'algoritmo, ottenuto direttamente come prima scomposizione del problema, è:
1) Inizio dell’algoritmo
2) acquisire dall’esterno il valore di n;
3) a ←2n
4) b ← a - 1
5) c ← a + b
6) Restituire c
7) Fine dell’algoritmo
Costruzione di algoritmi mediante analisi (segue)
Metodologia di soluzione dei problemi
• La scomposizione del problema in sotto-problemi più
piccoli (e quindi più semplici da risolvere) è
denominato approccio top-down, oppure divide et
impera o divide and conquer.
• Un altro approccio di che più essere utilizzato è l’
approccio bottom up, che parte dal caso base
(semplice) e costruisce via via una soluzione generale.
Flowcharts (diagrammi di flusso o a blocchi)
• Un diagramma di flusso o flowchart permette di realizzare una
descrizione grafica di un algoritmo.
-
• E’ detto diagramma di flusso in quanto permette di rappresentare
graficamente il flusso (cioè la sequenza) delle operazioni di cui
è composto l’algoritmo.
Flowcharts (segue)
• Ogni istruzione viene rappresentata da un blocco elementare
(o più semplicemente blocco).
• La forma grafica dei blocchi è determinata dal tipo dell’
istruzione.
• I blocchi sono etichettati con le istruzioni stesse.
• I blocchi sono collegati tra loro da frecce che indicano gli
schemi di flusso, cioè il susseguirsi delle azioni elementari.
Flowcharts (segue)
La struttura generale di un diagramma a blocchi è la
seguente:
a)
blocco iniziale;
b)
blocco finale;
c)
numero finito n (n ≥ 1) di blocchi di azione e/ o
di lettura-scrittura
d)
numero finito m (m ≥ 0) di blocchi di controllo
Flowcharts (segue)
Flowcharts (segue)
Esempio: Diagramma a blocchi dell'algoritmo per il calcolo di M.C.D. (a,b)
Flowcharts (segue).
Si noti come l'operazione "scambiare i valori di a e b" è stata realizzata con la sequenza di
assegnazioni
E’ stata usata una variabile di appoggio (in questo caso x) in quanto l'assegnazione è
distruttiva nel senso che quando si assegna un nuovo valore ad una variabile non si ha
memoria del suo valore precedente. Pertanto se le variabili a e b fossero:
una sequenza
assegnazioni
di
avrebbe
come
effetto
Flowcharts: calcolo (segue)
I Cicli (loop)
Un ciclo rappresenta essenzialmente uno schema di iterazione.
Un ciclo è definito quando si conosce a priori il numero di volte che deve essere eseguito. Un ciclo
definito è detto anche ciclo enumerativo.
●
●
In questo caso si usa la tecnica del contatore: una variabile, detta contatore del ciclo, che conta
quante volte istruzioni del ciclo sono state eseguite.
Il contatore del ciclo può essere utilizzato in due modi:
○ Incremento del contatore: il contatore viene inizializzato ad un valore minimo, ad
esempio 0, e incrementato di uno tutte le volte che il ciclo è eseguito. Si ha una uscita
dal ciclo quando il valore del contatore è uguale al numero prefissato di volte che il ciclo
deve essere eseguito (vedi esempio precedente).
○ Decremento del contatore: il contatore viene inizializzato con un valore uguale al numero
di volte che il ciclo deve essere eseguito e decrementato di uno ogni volta che il ciclo è
eseguito. Si ha una uscita quando il valore del contatore raggiunge il valore 0.
Un ciclo è indefinito quando non è possibile conoscere a priori quante volte deve essere eseguito.
In questo caso la condizione di fine ciclo viene fatta controllando valore di una o più variabili. I valori di
queste variabili sono modificati da istruzioni che fanno parte della iterazione.
Algoritmi iterativi
Accade molto spesso che, per risolvere un problema, lo stesso insieme di operazioni debba essere
eseguito un numero opportuno di volte.
Consideriamo ad esempio il seguente problema:
Calcolare la somma dei cubi dei tre numeri interi successivi ad un valore dato n.
(n+1)3+(n+2)3+(n+3)3
Un possibile algoritmo è il seguente:
Algoritmi iterativi (segue)
Il risultato è ottenuto usando la variabile somma
come un contenitore di somme parziali finché
non si ottiene la somma totale richiesta.
Questo risultato viene raggiunto eseguendo delle
azioni "simili" per un numero opportuno di volte.
Lo stesso risultato può essere ottenuto
modificando leggermente le istruzioni così che l’
algoritmo sia composto da un numero prefissato
di azioni uguali:
Algoritmi iterativi (segue)
In questo modo il valore finale di somma è ottenuto mediante l’esecuzione, per una sola volta, della
sequenza di istruzioni
E dalla esecuzione per tre volte della sequenza di istruzioni
Algoritmi iterativi (segue)
Algoritmi ricorsivi
Gli algoritmi ricorsivi sono algoritmi che “richiamano se stessi” per la risoluzione di un problema.
Molto semplici da scrivere e pensare, ma meno efficienti sul calcolatore degli algoritmi iterativi.
L'algoritmo include una sequenza di chiamate all’algoritmo stesso che ha termine al verificarsi di una
condizione particolare che viene chiamata condizione di terminazione, che in genere si ha con
particolari valori di input.
Esempio: Calcolo del fattoriale n!. Esso è definito come segue: 0!=1, 1!=1, n! = n *(n-1)!
NB: Ogni algoritmo ricorsivo può essere convertito in un algoritmo iterativo.
Vettori o array.
Un vettore o array è una variabile che può contenere un numero di elementi maggiore di uno.
Un array è di fatto una zona di memoria, all’interno del calcolatore, come una singola variabile.
La dimensione della zona di memoria allocata dal calcolatore per un array, è uguale alla quantità di
memoria necessaria per contenere una variabile singola moltiplicata per il numero di elementi dell’array
stesso.
Ciascuno “scomparto” si dice componente o elemento del vettore, la dimensione di
vettore è il numero dei suoi elementi.
un
La notazione comune per identificare un elemento di un array, è quello di usare il nome del
vettore stesso, seguito da una coppia di parentesi (tonde o quadre) che racchiudono il numero che
individua lo scomparto:
v(1)
oppure
v[4]
I vettori sono particolarmente utili quando è necessario effettuare lo stesso tipo
di operazionisu un insieme di dati.
Ogni volta che un vettore è usato in un algoritmo è necessario dichiararne le
caratteristiche
nell'elenco
delle
variabili usate.
Vettori (segue)
allora il vettore somma e è dato da
(somma per posizione a(1)+b(1), a(2)+b(2) etc )
Vettori.