esaminare una collezione di dati, cercando un particolare valore

Università di Roma “Tor Vergata”
L16 - 1
Ricerca:
esaminare una collezione di dati, cercando un
particolare valore
(per: • reperire informazione
• modificarla
• stamparla
• cancellarla
•…
)
esempio: archivio studenti
const int NUMSTUD = … ;
struct studente
{int matricola, string nome};
studente archivio[NUMSTUD ];
numero
matricola
0
1
2
•
•
•
NUMSTUD-1
Fondamenti di Informatica 1
6834
9132
8721
•
•
•
3254
nome e
cognome
"Mario Rossi" 0
"Anna Bianchi" 1
•
•
•
2
•
•
•
NUMSTUD-1
V. Grassi
Università di Roma “Tor Vergata”
L16 - 2
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
Ø
void RicLineare(studente A[], int n,
int valore, bool& trovato, int& indice);
↑
valore da
cercare
Fondamenti di Informatica 1
↑
vero se trovato
falso altrimenti
↑
indice elemento
trovato,se presente
V. Grassi
Università di Roma “Tor Vergata”
L16 - 3
esempio di chiamata (stampa il nome dello
studente con una certa matricola):
int i, numMatricola;
bool ok;
… ;
cin >> numMatricola;
… ;
RicLineare(archivio, NUMSTUD,
numMatricola, ok, i);
if (ok)
cout << archivio[i].nome;
else cout << "matricola inesistente";
definizione della funzione:
void RicLineare(studente A[], int n,
int valore, bool& trovato, int& indice);
{int cont;
cont = 0;
Æ inizializzazione
trovato = false;
while (cont<n && !trovato)
if (A[cont].matricola != valore)
cont = cont+1;
else trovato = true;
indice = cont;
Æ il valore di indice è significativo
}
solo se trovato
Fondamenti di Informatica 1
V. Grassi
Università di Roma “Tor Vergata”
L16 - 4
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
fl
mediamente il tempo di ricerca è proporzionale a
n
(O(n): dell’ordine di n)
Fondamenti di Informatica 1
V. Grassi
Università di Roma “Tor Vergata”
L16 - 5
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
6
7
20
21
40
41
56
60
77
80
Fondamenti di Informatica 1
V. Grassi
Università di Roma “Tor Vergata”
A:
0
1
2
3
4
5
6
7
A:
0
1
2
3
4
5
6
7
L16 - 6
1° tentativo (si considera tutto l’array)
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)
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
(con la ricerca lineare ne sarebbero stati
necessari 6)
Fondamenti di Informatica 1
V. Grassi
Università di Roma “Tor Vergata”
L16 - 7
in generale:
num. medio confronti con ricerca lineare:
O(n)
num. medio confronti con ricerca binaria
O(log n)
T
(tempo
medio)
ric. lineare
ric. binaria
n (dim. array)
esempio: se un confronto richiede 1 msec
n = 100 000 (105):
T(ric.lineare) ª 50 msec
T(ric.binaria) ª 17 msec
n = 10 000 000 (107):
T(ric.lineare) ª 5 sec
T(ric.binaria) ª 27 msec
definizione della funzione (i parametri hanno lo
stesso significato della funzione Riclineare):
Fondamenti di Informatica 1
V. Grassi
Università di Roma “Tor Vergata”
L16 - 8
void RicBinaria(studente 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].matricola>valore)
Æ si ricerca nellaprima metà
ultimo = mezzo-1;
else if (A[mezzo].matricola <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)
Fondamenti di Informatica 1
V. Grassi
Università di Roma “Tor Vergata”
L16 - 9
ordinamento:
dato un array, come disporre i 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
fi
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
Fondamenti di Informatica 1
V. Grassi
Università di Roma “Tor Vergata”
L16 - 10
esempio (in grigio la parte non ordinata):
passo 1:
A
0
1
2
3
4
A
primo
32
115
56
- 16
43
- 16
115
56
32
43
fi
più piccolo
passo 2:
A
A
- 16
115
56
32
43
- 16
32
56
115
43
primo
fi
più piccolo
passo 3:
A
A
- 16
32
56
115
43
- 16
32
43
115
56
primo
più piccolo
Fondamenti di Informatica 1
fi
fi
fi
fi
V. Grassi
Università di Roma “Tor Vergata”
L16 - 11
passo 4:
A
A
- 16
32
43
115
43
- 16
32
43
56
115
fi
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;
ciclo di ordinamento
}
numero di operazioni fatte da SelectionSort:
Fondamenti di Informatica 1
V. Grassi
Università di Roma “Tor Vergata”
1° passo
2° passo
L16 - 12
(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 msec
• per ordinare un array di n=100 000 elementi :
T(SelectionSort) ª (105)2msec ª (104) sec
ª 2.8 ore
T(n log(n) ) ª 105log(105)msec ª (175)msec
ª 1.7 sec
• per ordinare un array di n=10 000 000 elementi
:
T(SelectionSort) ª (107)2msec ª (108) sec
ª 3.17 anni
T(n log(n) ) ª 107log(107)msec ª 270 sec
ª 4.5 min
Fondamenti di Informatica 1
V. Grassi