Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Ricerca Sequenziale e Ricerca Binaria: Algoritmi Fondamentali in Informatica, Dispense di Elementi di Informatica

Due algoritmi fondamentali in informatica: la ricerca sequenziale e la ricerca binaria. Viene illustrata la logica di funzionamento di entrambi gli algoritmi, analizzando la loro complessità computazionale e il loro comportamento in diversi casi. Esempi pratici e spiega come la ricerca binaria, grazie alla sua efficienza, è particolarmente utile per la ricerca di elementi in sequenze ordinate.

Tipologia: Dispense

2011/2012

Caricato il 28/01/2025

peppegmx
peppegmx 🇮🇹

5 documenti

1 / 5

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Pag 24
3) Il problema della ricerca
Nell’informatica esistono alcuni problemi particolarmente rilevanti, poiché essi:
si incontrano in una grande varietà di situazioni reali;
appaiono come sottoproblemi da risolvere nell’ambito di problemi più complessi.
Uno di questi problemi è la ricerca di un elemento in un insieme di dati (ad es. numeri, cognomi,
ecc.).
Iniziamo a definire un po’ più formalmente tale problema definendone l’input e l’output:
Input: un vettore A di n numeri ed un valore v;
Output: un indice i tale che A[i] = v, oppure un particolare valore null se il valore v non
è presente nel vettore.
3.1 Ricerca sequenziale
Un primo semplice algoritmo che viene in mente è ispezionare uno alla volta gli elementi del
vettore, confrontarli con v e alla fine restituire il risultato. Ci si interrompe appena si trova v:
Funzione Ricerca (A: vettore; v: intero)
i 1
while ((i ≤ n) and (A[i] ≠ v))
i i + 1
if (i n)
return i
else
return null
Oppure:
Funzione Ricerca (A: vettore; v: intero)
i 1
for (i = 1 to n)
if (A[i] = v) return i
return null
Questo algoritmo ha una complessità di Ө(n) nel caso peggiore (quando, cioè, v non è
contenuto nel vettore) e di Ө(1) nel caso migliore (quando v viene incontrato per primo), quindi
non abbiamo trovato una stima della complessità che sia valida per tutti i casi. In queste
pf3
pf4
pf5

Anteprima parziale del testo

Scarica Ricerca Sequenziale e Ricerca Binaria: Algoritmi Fondamentali in Informatica e più Dispense in PDF di Elementi di Informatica solo su Docsity!

3) Il problema della ricerca

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

 si incontrano in una grande varietà di situazioni reali;

 appaiono come sottoproblemi da risolvere nell’ambito di problemi più complessi.

Uno di questi problemi è la ricerca di un elemento in un insieme di dati (ad es. numeri, cognomi, ecc.).

Iniziamo a definire un po’ più formalmente tale problema definendone l’input e l’output:

 Input: un vettore A di n numeri ed un valore v ;

 Output: un indice i tale che A[i] = v , oppure un particolare valore null se il valore v non

è presente nel vettore.

3.1 Ricerca sequenziale

Un primo semplice algoritmo che viene in mente è ispezionare uno alla volta gli elementi del vettore, confrontarli con v e alla fine restituire il risultato. Ci si interrompe appena si trova v :

Funzione Ricerca (A: vettore; v: intero)

i  1 while ((i ≤ n) and (A[i] ≠ v)) i  i + 1 if (i ≤ n) return i else return null

Oppure:

Funzione Ricerca (A: vettore; v: intero)

i  1 for (i = 1 to n) if (A[i] = v) return i return null

Questo algoritmo ha una complessità di Ө (n) nel caso peggiore (quando, cioè, v non è contenuto nel vettore) e di Ө (1) nel caso migliore (quando v viene incontrato per primo), quindi non abbiamo trovato una stima della complessità che sia valida per tutti i casi. In queste

situazioni diremo che la complessità computazionale dell’algoritmo (in generale, non nel caso peggiore) è un O(n) , per evidenziare il fatto che ci sono input in cui questo valore viene raggiunto, ma ci sono anche input in cui la complessità è minore.

Nei casi, come questo, in cui non sia possibile determinare un valore stretto per la complessità computazionale, ed in cui il caso migliore e quello peggiore si discostano, è naturale domandarsi quale sia la complessità dell’algoritmo nel caso medio.

Supponiamo che v possa apparire con uguale probabilità in qualunque posizione, ossia che

P(v si trova in i-esima posizione) =

Allora il numero medio di iterazioni del ciclo è dato da:

Un metodo alternativo è il seguente. Supponiamo che tutte le possibili n! permutazioni della sequenza di n numeri siano equiprobabili. Di queste, ve ne saranno un certo numero nelle quali v appare in prima posizione, un certo numero nelle quali v appare in seconda posizione, ecc.

Il numero medio di iterazioni del ciclo sarà di conseguenza:

numero medio di iterazioni =

Ora, il numero di permutazioni nelle quali v appare nella i -esima posizione è uguale al numero delle permutazioni di (n-1) elementi, dato che fissiamo solo la posizione di uno degli n elementi, cioè (n – 1)!. Quindi:

numero di iterazioni = = =

Con un metodo diverso abbiamo trovato lo stesso risultato. Dunque, la complessità del caso medio è un Ө(n).

3.2 Ricerca binaria

E’ possibile progettare un algoritmo più efficiente nel caso in cui la sequenza degli elementi sia ordinata (come sono, ad esempio, i cognomi degli abbonati nell’elenco telefonico).

Come cerchiamo un nome nell’elenco telefonico? Iniziamo sempre e comunque dalla prima lettera dell’alfabeto? Ovviamente no… andiamo direttamente a una pagina dove pensiamo di trovare cognomi che iniziano con la lettera giusta; se siamo precisi troviamo il nome nella pagina, altrimenti ci spostiamo in avanti o indietro (di un congruo numero di pagine) a seconda che la lettera del cognome che cerchiamo venga prima o, rispettivamente, dopo quelle delle iniziali dei cognomi contenuti nella pagina.

 v è presente nella sequenza (altrimenti si ricade nel caso peggiore);

 tutte le posizioni di v fra 1 e n sono equiprobabili.

Domandiamoci ora quante siano le posizioni raggiungibili alla i -esima iterazione:

 con una iterazione si raggiunge la posizione i = n/2 ;

 con due iterazioni si raggiungono due posizioni: i = , i = ;

 con tre iterazioni si raggiungono quattro posizioni: i = , i = , i = , i = ;

 e così via.

In generale, l’algoritmo di ricerca binaria esegue i iterazioni se e solo se v si trova in una delle 2 i-1^ posizioni raggiungibili con tale numero di iterazioni.

Chiamando n(i) il numero delle posizioni raggiungibili con i iterazioni, possiamo scrivere che il numero medio di iterazioni è:

numero medio di iterazioni = =

Ma ricordando che: = (k-1) 2 k^ + 1

otteniamo:

Ossia, il numero medio di iterazioni si discosta per meno di un confronto dal numero massimo di iterazioni!

Infine, consideriamo una nuova formulazione dell’algoritmo di ricerca binaria (nella quale sono volutamente tralasciati i dettagli per catturarne l’essenza):

Ricerca_binaria (A, v)

se il vettore è vuoto restituisci null ispeziona l’elemento A[centrale] se esso e’ uguale a v restituisci il suo indice se v < A[centrale] esegui Ricerca_binaria (metà sinistra di A, v) se v > A[centrale] esegui Ricerca_binaria (metà destra di A, v)

L’aspetto cruciale di questa formulazione risiede nel fatto che l’algoritmo risolve il problema “riapplicando” se stesso su un sottoproblema (una delle due metà del vettore).

Questa tecnica si chiama ricorsione , ed è un argomento importantissimo che sarà illustrato nel prossimo capitolo.