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