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 12n 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)2sec (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)2sec (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