CORSO DI PROGRAMMAZIONE II

Slides:



Advertisements
Presentazioni simili
Calcolo di valori approssimati delle radici
Advertisements

Iterazione while – do while - for.
Struttura di un programma
Linguaggio C++ Operatori – numeri pseudocasuali - costanti.
Numeri casuali.
Procedure e funzioni In linguaggio C.
Introduzione ad Array e Funzioni 2IC/2ID – a. s.2012/13.
Generazione di numeri casuali in Dev C++
I DATI LE ISTRUZIONI LE STRUTTURE FONDAMENTALI
© 2007 SEI-Società Editrice Internazionale, Apogeo Unità F3 Iterazione.
Le funzioni.
Il problema del … problema! Si definisce problema una situazione in cui vengono fornite delle informazioni e ne vengono richieste altre: Le informazioni.
Noi siamo EQUIVALENTI perché
Esercitazione 5 Esercizio 3 (radice quadrata con metodo di Newton)
PROGRAMMI DI RICERCA E ORDINAMENTO
Informatica 2. Concetti fondamentali di programmazione Programmare vuol dire scrivere un algoritmo in un linguaggio che faccia funzionare un calcolatore.
Algoritmi numerici Zeri di una funzione Integrale di una funzione
I numeri figurati Numeri quadrati: Numeri triangolari:
dal particolare al generale
CORSO DI PROGRAMMAZIONE II Introduzione alla ricorsione
CORSO DI PROGRAMMAZIONE II
Algoritmi e Strutture Dati Valutazione del tempo di esecuzione degli algoritmi.
Introduzione alla programmazione ll
chi ha paura della matematica?
Studente Claudia Puzzo
Fondamentidi Programmazione Corso: Fondamenti di Programmazione Classe: PARI-DISPARI Docente: Prof. Luisa Gargano Testo: Aho, Ulman, Foundations of Computer.
ITERAZIONE e RICORSIONE (eseguire uno stesso calcolo ripetutamente)
Gli algoritmi.
Equazioni non lineari Data una funzione consideriamo il problema di determinare i valori x tali che Tali valori sono solitamente.
Fibonacci Heaps e il loro utilizzo nell’algoritmo di Prim
Elementi di Informatica di base
Esercizio 10.* Un cassiere vuole dare un resto di n centesimi di euro usando il minimo numero di monete. a) Descrivere un algoritmo goloso per fare ciò.
Particolari terne numeriche e teorema di PITAGORA
Università degli Studi di BresciaA.A. 2012/2013 Fondamenti di Programmazione Docente: Alessandro SaettiA.A. 2012/2013 Università degli Studi di Brescia.
Lezione 6 Strutture di controllo Il condizionale
In molti casi è utile assegnare a degli identificatori dei valori che restino costanti durante tutto il programma e che non possano essere cambiati nemmeno.
Il Teorema di Pitagora.
CIRCONFERENZA E CERCHIO
Cominciamo a parlare di tangenti.
TEOREMA DI PITAGORA.
Un approccio soft per i primi tre anni della primaria
La complessità media O(n log n) di Quick-Sort vale soltanto se tutte le permutazioni dell’array in ingresso sono ugualmente probabili. In molte applicazioni.
Radice quadrata di un numero
Estrazione di radice.
GLI ARRAY MONODIMENSIONALI. Utilizzando le nostre attuali conoscenze, proviamo a risolvere il seguente problema: Calcolare la media dei voti conseguiti.
TEOREMA DI PITAGORA In un qualsiasi triangolo rettangolo il quadrato costruito sull’ipotenusa è equivalente alla somma dei quadrati costruiti sui due cateti.
Equazioni e sistemi non lineari
R 255 G 211 B 8 R 255 G 175 B 0 R 127 G 16 B 162 R 163 G 166 B 173 R 104 G 113 B 122 R 234 G 234 B 234 R 175 G 0 B 51 R 0 G 0 B 0 R 255 G 255 B 255 Supporting.
Algoritmi e Strutture Dati
CORSO DI PROGRAMMAZIONE II
Il valore finanziario del tempo Il costo opportunità del capitale
Vicario, Pasquali, Delfini, Pradella, Fincato
Scrivere e compilare programmi
Il Problema del Commesso Viaggiatore. Traveling Salesman’s Problem (TSP) Un commesso viaggiatore deve visitare un certo numero di città Conosce la distanza.
L’ordinamento per Selezione seleziona l’elemento con valore maggiore e lo scambia con il primo elemento del vettore. Tra gli N-1 elementi rimanenti viene.
Algoritmi e Programmazione (in C) Stefano Cagnoni e Monica Mordonini
Informatica e Informatica di Base
Problemi, algoritmi e programmazione
Calcolo delle Aree Area del Cerchio Il calcolo dell’area è molto più complesso in quanto non è possibile scomporre il cerchio in triangoli. E’ possibile.
Frazioni e problemi.
I problemi con le frazioni, siano essi di geometria o di aritmetica, generano a volte negli alunni una serie di difficoltà riconducibili a motivazioni.
ALGORITMO PER IL CALCOLO DELLA RADICE QUADRATA DI UN NUMERO METODO DI NEWTON Carlo Platella
32 = 9 x2 = 9 x = 3 32 = 9 √9 = 3 L’estrazione di radice
La misura della circonferenza e del cerchio
Istruzioni e algoritmi. Istruzioni Operative I passi elementari che compongono l’algoritmo sono le istruzioni. Distinguiamo: Istruzioni di input Istruzioni.
Lezioni di Ricerca Operativa Corso di Laurea in Informatica
Dal PROBLEMA all’ALGORITMO
Algoritmi Avanzati a.a.2013/2014 Prof.ssa Rossella Petreschi Albero ricoprente di costo minimo Lezione n°12.
Lezione n. Parole chiave: Corso di Laurea: Insegnamento: Docente: A.A Salvatore Cuomo La ricorsione 15 Approccio ricorsivo, esercizi sulla.
Operatori – numeri pseudocasuali - costanti
Transcript della presentazione:

CORSO DI PROGRAMMAZIONE II Lezione 8 Algoritmi di ricerca prof. E. Burattini a.a. 2010-2011

Un caso di studio: il calcolo della radice quadrata. Il modo più semplice per calcolare la radice quadrata di un numero “a” è quello di utilizzare un algoritmo molto antico, usato dai babilonesi, e riproposto da Erone, che consiste nell’utilizzare la formula ricorrente Xs = _________________ 2 dove Xp è il valore precedente e Xs è quello successivo. Per poter applicare questa formula è necessario assegnare un valore iniziale a Xp; poiché Xp appare anche al denominatore poniamo come valore iniziale Xp=1. Xp + a Xp Volendo calcolare la radice di 2, seguiamo i primi passi dell’algoritmo: Xp=1 Xs=(1+2)/2=1,5 Poniamo ora Xp=1,5 Xs=(1,5+2/1,5)/2=1,416 Poniamo ora Xp=1,416 e così via

L’algoritmo si sviluppa sulla base di alcune osservazioni geometriche. L’algoritmo di Erone di Alessandria (vissuto tra il I° e II° sec. d.C.) utilizza solo le quattro operazioni dell’aritmetica. L’algoritmo si sviluppa sulla base di alcune osservazioni geometriche. Dato un numero A se costruiamo un quadrato di area A, il lato di questo quadrato sarà proprio la radice di A Per costruire questo quadrato eseguiamo una serie di approssimazioni successive partendo da un rettangolo i cui lati misurano h e A/h, con h minore di A. L’area del rettangolo è cioè è uguale all’area del quadrato che cerchiamo. I lati sono invece uno minore e uno maggiore del lato del quadrato. A A

Calcoliamo ora la media aritmetica delle misure dei due lati del rettangolo, Avremo ovviamente che h1 è maggiore di h. Costruiamo un nuovo rettangolo i cui lati misurano h1 e A A

Calcolando di nuovo la media aritmetica delle misure dei due lati Avremo ancora che l’area del rettangolo, pari a resta uguale a quella del quadrato, mentre h1 è un valore approssimato per eccesso del lato del quadrato, mentre è un valore approssimato per difetto. La media aritmetica così ottenuta fornisce ora un valore h1 più vicino a VA di quanto lo fosse h. Calcolando di nuovo la media aritmetica delle misure dei due lati del rettangolo, otteniamo dove ancora h2 è maggiore di h1 ma sempre minore di A. A A A

Reiteriamo il processo costruendo il rettangolo i cui lati misurano h2 e . Avremo un valore approssimato per eccesso del lato del quadrato e un valore approssimato per difetto. Il valore di h2 è però più vicino a A di quanto lo fosse h1. Proseguendo per questa strada, cioè con successive approssimazioni, costruiamo due successioni di numeri che approssimano, una per eccesso e una per difetto, la radice quadrata di A. A

passo2 passo3 passo1 …………. Quadrato da costruire 20,5 19,5 l =400 A 20 h 10 40 25 16 A h A A …………. A Quadrato da costruire

Nella prossima diapositiva si mostra l’algoritmo di Erone mediante un algoritmo iterativo. Viene richiesto il valore dell’approssimazione che si vuole ottenere per il calcolo della radice quadrata () e quindi iterativamente, tramite un ciclo si esegue l’algoritmo fin quando l’approssimazione ottenuta non è minore di .

Un codice iterativo è il seguente: #include <iostream> #include <cstdlib> #include <cmath> using namespace std; // Calcola radice quadrata main () { const float eps=0.000001; float a,x ; // precondizioni: a>=0 and eps>0 cout << " Calcolo della radice di a: a="; cin >> a; x=1.0; while (fabs(x-a/x)/2>=eps) x=(x+a/x)/2; //Postcondizioni: x>0 |x-a/x|<eps cout <<"Radice di "<< a <<"="<< x <<endl; system(“pause”); }

L’algoritmo di Erone si presta perfettamente ad una sua interpretazione in chiave ricorsiva. Il caso base è rappresentato dal raggiungimento del valore di approssimazione  richiesta, mentre la chiamata ricorsiva riproduce la formula di Erone.

// La Radice Quadrata con il metodo di Erone // DEFINIZIONI double radice(double a,double eps1,double &x1) { if ((fabs(x1-a/x1)/2)>=eps1) { x1=(x1+a/x1)/2; return radice(a,eps1,x1); } else return x1; } Allegato: radice quadrata

ALGORITMI DI RICERCA LINEARE Problema: Cercare tra i valori contenuti in un Array un preassegnato valore. Esempio: Data una lista di N numeri verificare se esiste un preassegnato Un algoritmo ricorsivo, che risolva questa problema presenta due casi base: - la ricerca è finita se nessun elemento uguale a quello cercato esiste - la ricerca è finita se almeno un elemento uguale a quello cercato è stato trovato Supponiamo di partire dall’ultimo elemento della lista e risalire fino in cima nella ricerca dell’elemento.

Soluzione iterativa: Gestire opportunamente l’indice dell’array in cui sono contenuti gli elementi su cui fare la ricerca. I criteri per stabilire il nuovo valore da attribuire all’indice possono essere i più diversi. E’ però importante che una volta stabilito che un elemento individuato da un certo indice non è quello cercato questo elemento non venga più esaminato. Di seguito si mostra una versione iterativa. Si noti che poiché ad ogni passo della ricerca eliminiamo un elemento il massimo numero di passi che potranno essere eseguiti è pari al numero di elementi.

Algoritmo di ricerca: soluzione iterativa. // MAIN { Indicatore= CercaIndice(Nome, NumeroElementi,ValoreCercato); IF (Indicatore>=0) cout<<ValoreCercato<<” è stato trovato nella posizione “<<Indicatore; ELSE cout<< ValoreCercato<<“ non è stato trovato “<<endl; } int CercaIndice(int Nome[], int NumeroElementi, int ValoreCercato) int Indice; bool Trovato; { while (Indice>0) && ( Trovato!=1) { if (Nome[Indice]==ValoreCercato) Trovato= true else Indice= Indice-1; } return Indice; }

La versione ricorsiva dello stesso algoritmo è la seguente int RicercaLinRic(int a[],int i, int Chiave) { if (i<0) return -1; else // prendi un Candidato if (a[i] == Chiave) return i; // rivedi il SubRange riducendo le dimensioni del problema return RicercaLinRic(a, i-1, Chiave); } 1° caso base 2° caso base Chiamata ricorsiva

Caratteristiche di una ricerca ricorsiva Una chiamata ricorsiva implica sempre una riduzione del sub range di possibili candidati. Quindi nell’intestazione è presente almeno un parametro che rappresenta il subrange di elementi. Il valore del parametro in ogni istante di computazione è funzione di un qualche subrange candidato locale. Questa espressione, i cui valori devono rappresentare una riduzione del subrange candidato, viene calcolata e al successivo processo di ricerca i valori ottenuti vengono applicati.

Caratteristiche di una ricerca ricorsiva La condizione di terminazione è espressa in termini dei parametri del subrange candidato. Questa condizione rappresenta il caso base quando non restano altri subrange candidati alla ricerca. L’altro caso base si ha quando la ricerca ha buon esito, quando cioè a[Candidato] coincide con Chiave.

Ricerca binaria Assegnato un vettore ordinato A di interi, di dimensione N, determinare la posizione di un elemento mediante una ricerca binaria. Ricordiamo che la ricerca binaria si basa sulla tecnica del divide et impera.

Ricerca binaria Dividiamo gli elementi in due parti; essendo tutti gli elementi ordinati, confrontiamo l’elemento cercato x con il valore M che separa le due parti: se x<M allora dobbiamo continuare a cercare nella prima parte, altrimenti cercheremo nella seconda parte. Dividiamo la parte scelta ancora in due e applichiamo sempre il ragionamento precedente. L’algoritmo termina o quando l’ultimo elemento rimasto dalle successive suddivisioni è uguale a quello cercato, oppure quando l’intervallo rimasto non è più suddivisibile il che implica che il nostro elemento non appartiene al vettore. 19 19

Un algoritmo iterativo per la ricerca binaria è il seguente: // BINARIA ITERATIVA // basso=indice più piccolo, alto=indice più grande del vettore int RicercaBinIter ( int vet[], int basso, int alto, int x) { int medio, i=-1; while ((basso<=alto) && i==-1) medio=(basso+alto)/2; if (vet[medio]==x) i=medio ; else if (vet[medio]<x) basso=medio+1; alto=medio-1; } return i; Si noti che la variabile i, inizialmente posta =-1, cambia solo se troviamo il dato cercato, quindi se in uscita, la funzione ritorna -1, implica che il dato cercato non è stato trovato.

Ricerca binaria ricorsiva Scriviamo la funzione tenendo presente che vet[] è il vettore di interi, x è l’elemento da cercare, basso rappresenta l’indice minimo, alto quello massimo del vettore di interi int RicercaBinRic (int vet[],int x, int basso, int alto ) if (basso>alto) // è stato analizzato tutto il vettore senza trovare l’elemento x: primo CASO BASE else Medio = (basso+alto) / 2; if (vet[Medio]==x) // la funzione deve restituire l’indice Medio : secondo CASO-BASE if (vet[Medio] < x) // deve richiamare le funzione nella metà superiore dell’array // deve richiamare le funzione nella metà inferiore dell’array

Il codice è pertanto il seguente. int RicercaBinRic (int vet[],int x, int basso, int alto ) { int Medio; if (basso>alto) return -1; else Medio = (basso+alto) / 2; if (vet[Medio]==x) return Medio; if (vet[Medio] < x) return RicercaBinRic (vet, x, Medio+1, alto); return RicercaBinRic (vet, x, basso, Medio-1); }

Esercizio Scrivere una funzione ricorsiva che ritorna vero se gli elementi di UnArray di interi, con valori assegnati nel subrange 1..TotElem, sono in ordine crescente. Obiettivo: ricercare un elemento che sia fuori ordine in un dato subrange. Ridurre di volta in volta il subrange fino a quando in questo resta un solo elemento allora vuol dire che la ricerca è finita e la risposta è TRUE. Se invece si verifica che è vera l’espressione UnArray[N-1]>UnArray[N] questo significa che è stato trovato un elemento non in ordine e la funzione ritorna FALSE.

ESERCIZIO Con una function ricorsiva, utilizzando la tecnica dell’INSERTION SORT, inserire in maniera ordinata, in un array di numeri interi, i valori letti da tastiera fin quando non si introduce lo 0. insfinale

void InsertionRic(int a[], int &fine,int j, int &elemento) { if (elemento==0) return; else if (j==0) { a[0]=elemento; fine=fine+1; cout<<" Elemento "; cin>>elemento; return InsertionRic(a,fine,fine,elemento); } else { if (a[j-1]>elemento) { a[j]=a[j-1]; return InsertionRic(a,fine,j-1,elemento); } { a[j]=elemento; Allegato insertion