lucidi_L13 - Università degli Studi di Roma "Tor Vergata"

Università di Roma “Tor Vergata”
Ricerca:
esaminare una collezione di dati, cercando un
particolare valore
(per: • reperire informazione
• modificarla
• stamparla
• cancellarla
•…
)
esempio: archivio studenti
const int NUMSTUD = … ;
const int LUNGHNOME = … ;
typedef char stringa[LUNGHNOME ];
int matricole[NUMSTUD ];
stringa nomi[NUMSTUD ];
numero
matricol
a
0
2
6834
9132
8721
•
•
1
L13
1
nome e
cognome
"Mario Rossi" 0
"Anna Bianchi" 1
2
•
Fondamenti di Informatica 1 - Vincenzo Grassi
•
Università di Roma “Tor Vergata”
•
•
•
•
•
•
•
•
NUMSTUD-1
NUMSTUD-1
3254
problema di ricerca:
data una matricola (valore), determinare l’indice
della posizione in cui si trova (se c’è)
1a soluzione: ricerca lineare (o “completa”)
algoritmo:
confronta 1° elem. con valore
se uguali STOP, altrimenti
confronta 2° elem. con valore
se uguali STOP, altrimenti
…
fino (al più) ad esaurimento elementi
dichiarazione funzione:
array in cui
cercare

dimensione
array
valore da
cercare


void RicLineare(int A[], int n, int valore,
bool& trovato, int& indice);

L13
2
Fondamenti di Informatica 1 - Vincenzo Grassi

Università di Roma “Tor Vergata”
vero se trovato
falso altrimenti
L13
3
Fondamenti di Informatica 1 - Vincenzo Grassi
indice elemento
trovato, se presente
Università di Roma “Tor Vergata”
esempio di chiamata (stampa il nome dello
studente con una certa matricola):
int i, numMatricola;
bool ok;
… ;
cin >> numMatricola;
… ;
RicLineare(matricole[], NUMSTUD,
numMatricola, ok, i);
if (ok)
cout << nomi[i];
else cout << "matricola inesistente";
definizione della funzione:
void RicLineare(int A[], int n, int valore,
bool& trovato, int& indice)
{int cont;
cont = 0;
 inizializzazione
trovato = false;
while (cont<n && !trovato)
if (A[cont] != valore)
cont = cont+1;
else trovato = true;
indice = cont;
 il valore di indice è significativo
}
solo se trovato
L13
4
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
vantaggio ricerca lineare:
• applicabile a qualsiasi array (anche non
ordinato)
svantaggio:
• molto lenta se n è grande
caso peggiore: n confronti
caso migliore: 1 confronto
12n  n+1 confronti
caso medio:
n
2

mediamente il tempo di ricerca è proporzionale a
n
(O(n): dell’ordine di n)
L13
5
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
2a soluzione: ricerca binaria
richiede che l’array sia ordinato
(rispetto al valore cercato)
algoritmo:
se (elemento di mezzo == valore cercato)
allora STOP
se (elemento di mezzo > valore cercato)
allora prosegui ricerca nella prima
metà dell’array
se (elemento di mezzo < valore cercato)
allora prosegui ricerca nella seconda
metà dell’array
esempio:
ricerca del valore 60 (in un array ordinato !!)
A:
0
1
2
3
4
5
L13
6
20
21
40
41
56
60
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
6
7
L13
77
80
7
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
1° tentativo (si considera tutto l’array)
A:
0
1
2
3
4
5
6
7
20
21
40
41
56
60
77
80
 primo ==0
mezzo==(primo+ultimo)/2==(0+7)/2==3
(confronto fallito !)
 ultimo ==7
2° tentativo (si considera la seconda metà,
perchè A[3]<60)
A:
0
1
2
3
4
5
6
7
20
21
40
41
56
60
77
80
 primo ==mezzo+1==3+1==4
mezzo==(primo+ultimo)/2==(4+7)/2==5
(trovato !!)
 ultimo ==7
nota: solo 2 confronti
L13
8
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
(con la ricerca lineare ne sarebbero stati
necessari 6)
L13
9
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
in generale:
num. medio confronti con ricerca lineare:
O(n)
num. medio confronti con ricerca binaria
O(log n)
T
(t e m p o
m eio)d
ric. in lere a
ric.
aria
b i n
n (d m.
i rr ay)
a
esempio: se un confronto richiede 1 sec
n = 100 000 (105):
T(ric.lineare)  50 msec
T(ric.binaria)  17 sec
n = 10 000 000 (107):
T(ric.lineare)  5 sec
L13
10
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
T(ric.binaria)  27 sec
definizione della funzione (i parametri hanno lo
stesso significato della funzione Riclineare):
void RicBinaria(int A[], int n, int valore,
bool& trovato, int& indice)
{int primo, ultimo, mezzo;
trovato = false;

inizializzazione
primo = 0;
ultimo = n-1;
while (primo<=ultimo && !trovato)
{mezzo = (primo+ultimo)/2;
if (A[mezzo]>valore)  si ricerca nella
prima metà
ultimo = mezzo-1;
else if (A[mezzo]<valore) 
si ricerca
nella seconda metà
primo = mezzo+1;
else trovato = true;
}
indice = mezzo;
}
il valore di indice è significativo
solo se trovato
questa è una versione non “ricorsiva”
(nella dispensa, anche versione ricorsiva)
L13
11
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
ordinamento:
dato un array, come disporre in suoi elementi in
ordine? (crescente o decrescente)
0
1
2
3
n-1 =
4
A
A
32
115
56
- 16
43
- 16
32
43
56
115

0
1
2
3
4
selection sort (o anche bubble sort):
algoritmo:
• esegui n-1 passi
• ad ogni passo, prendi la parte non ordinata
dell’array, e sposta nella sua 1a posizione il
più
piccolo elemento di quella parte (scambiando
con il valore corrente)
• ripeti, riducendo di una posizione la parte non
ordinata
L13
12
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
L13
13
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
esempio (in grigio la parte non ordinata):
passo 1:
A
0
32
115
56
- 16
43
1
2
3
4
A
primo
- 16
115
56
32
43

più piccolo
passo 2:
A
A
- 16
115
56
32
43
- 16
32
56
115
43
primo

più piccolo
passo 3:
A
A
- 16
32
56
115
43
- 16
32
43
115
56
L13
14
primo

più piccolo
Fondamenti di Informatica 1 - Vincenzo Grassi



Università di Roma “Tor Vergata”
passo 4:
A
A
- 16
32
43
115
43
- 16
32
43
56
115

primo
più piccolo
in totale 4 = 5-1 passi
ciclo di ordinamento:
for (inizio=0; inizio<(n-1); inizio++)
{ determina l’indice del più piccolo
elemento in A[inizio..n-1]
Scambia(A[inizio], A[piu_picc]);
}
determinazione indice del più piccolo elemento:
piu_picc = inizio;
for (i=inizio+1; i<n; i++)
if (A[i]<A[piu_picc])
piu_picc = i;
intestazione funzione:
void SelectionSort(int A[], int n)
{int inizio, piu_picc, i;
L13
15
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
}
ciclo di ordinamento
numero di operazioni fatte da SelectionSort:
1° passo
2° passo
(n-1)° passo
(n-1) + (n-2) + … + 2  n2
 O(n2)



numero confronti nel “for” interno (ricerca più
piccolo)
algoritmi di ricerca più efficienti (vedi libro di
testo):
O(n log(n) )
esempio:
se un confronto richiede 1 sec
• per ordinare un array di n=100 000 elementi :
T(SelectionSort)  (105)2sec  (104) sec
 2.8 ore
T(n log(n) )  105log(105)sec  (175)sec
 1.7 sec
• per ordinare un array di n=10 000 000 elementi
:
L13
16
Fondamenti di Informatica 1 - Vincenzo Grassi
Università di Roma “Tor Vergata”
T(SelectionSort)  (107)2sec  (108) sec
 3.17 anni
T(n log(n) )  107log(107)sec  270 sec
 4.5 min
L13
17
Fondamenti di Informatica 1 - Vincenzo Grassi