Scopo: ordinare una sequenza di elementi gli elementi siano

annuncio pubblicitario
ALGORITMI DI ORDINAMENTO
• Scopo: ordinare una sequenza di elementi
in base a una certa relazione d’ordine
– lo scopo finale è ben definito
→ algoritmi equivalenti
– diversi algoritmi possono avere
efficienza assai diversa
• Ipotesi:
gli elementi siano memorizzati in un array.
ALGORITMI DI ORDINAMENTO
Principali algoritmi di ordinamento:
•
•
•
•
•
•
naïve sort (semplice, intuitivo, poco efficiente)
bubble sort (semplice, un po’ più efficiente)
shell sort (generalizza bubble, efficienza media)
insert sort (intuitivo, abbastanza efficiente)
quick sort (non intuitivo, alquanto efficiente)
merge sort (non intuitivo, molto efficiente)
Ci concentreremo su quelli evidenziati.
ISTRUZIONI DOMINANTI
ALCUNI ALGORITMI SIGNIFICATIVI
• Negli algoritmi di ordinamento di un array e di
ricerca di un elemento in un array, l’istruzione
dominante è il confronto fra elementi.
Ordinamento di un array
• naive sort l'algoritmo più semplice, il primo che
Esempio: ricerca di un elemento in un array di interi
boolean ricerca (int v[], int el){
int i=0;
boolean trovato = false;
while (i<N) {
istruzioni dominanti
if (el == v[i])
trovato = true;
i++;
N+1 confronti nel while
}
N confronti nell’ if
return trovato;
→ costo lineare O(N)
}
NAÏVE SORT
Specifica
(sia n la dimensione dell’array v)
while (<array non vuoto>) {
<trova la posizione p del massimo>
if (p<n-1) <scambia v[n-1] e v[p] >
/* così v[n-1] contiene sempre il massimo */
<restringi l’attenzione alle prime n-1 caselle
dell’ array, ponendo n’ = n-1 >
}
viene in mente… ma anche il meno efficiente
• bubble sort un algoritmo ancora abbastanza
semplice, un po' più efficiente del precedente nel
caso medio (non nel caso peggiore)
Ricerca in un array ordinato
• ricerca binaria un algoritmo semplice ma molto
efficiente, che sfrutta l'ipotesi di array ordinato
NAÏVE SORT
Codifica in C (o Java)
void naiveSort(int v[], int n){
int p;
La dimensione dell’array
cala di 1 a ogni giro
while (n>1) {
p = trovaPosMax(v,n);
if (p<n-1) /* scambia elementi */
{ int t=v[p]; v[p]=v[n-1]; v[n-1]=t; }
n--;
}
}
1
NAÏVE SORT
NAÏVE SORT
Codifica in C (o Java)
int trovaPosMax(int v[], int n){
int i, posMax=0;
All’inizio si assume v[0]
come max di tentativo.
for (i=1; i<n; i++)
if (v[posMax]<v[i]) posMax=i;
return posMax;
}
Valutazione di complessità
• Il numero di confronti necessari vale sempre:
(N-1) + (N-2) + (N-3) + … + 2 + 1 =
= N*(N-1)/2 = O(N2/2)
• Importante:
– l’algoritmo fa gli stessi confronti sia per un array disordinato, sia per un array già ordinato!!
Si scandisce l’array e, se si trova un elemento
maggiore del max attuale, lo si assume come
nuovo max, memorizzandone la posizione.
BUBBLE SORT
BUBBLE SORT
• Corregge il difetto principale del naïve sort:
quello di non accorgersi se l’array, a un
certo punto, è già ordinato.
• Corregge il difetto principale del naïve sort:
quello di non accorgersi se l’array, a un
certo punto, è già
ordinato.
Può accadere anche alla prima
• Opera per “passate successive” sull’array:
“passata”,
se l’array è già
ordinato
• Opera per “passate
successive”
sull’array:
– a ogni “passata”, considera una ad una tutte le
possibili coppie di elementi adiacenti, scambiandoli se risultano nell’ordine errato
– così, dopo ogni passata, l’elemento massimo è
in fondo alla parte di array considerata
– a ogni “passata”, considera una ad una tutte le
possibili coppie di elementi adiacenti, scambiandoli se risultano
nell’ordine
Accorgendosi
di array già
ordinati, errato
evita
lavoro
inutile.
–l’algoritmo
così, dopo
ogni
passata,
l’elemento massimo è
in fondo alla parte di array considerata
• Quando non si verificano scambi, l’array è
ordinato, e l’algoritmo termina.
• Quando non si verificano scambi, l’array è
ordinato, e l’algoritmo termina.
BUBBLE SORT
BUBBLE SORT
Esempio
Codifica
void bubbleSort(int v[], int n){
int i; boolean ordinato = false;
while (n>1 && !ordinato){
Continua solo se
ordinato = true;
l’array non è ancora
for (i=0; i<n-1; i++)
ordinato.
if (v[i]>v[i+1]) {
int t=v[i]; v[i]=v[i+1]; v[i+1]=t;
ordinato = false; }
n--;
A ogni iterazione ipotizza che l’array sia ordinato,
}
poi verifica: se si deve fare anche solo uno
}
scambio, non era vero.
Iª passata (dim. = 4)
al termine, 7 è a posto.
IIª passata (dim. = 3)
al termine, 6 è a posto.
IIIª passata (dim. = 2)
al termine, 4 è a posto.
array ordinato
2
RIFERIMENTI
Alcuni link a cui si trovano algoritmi di ordinamento e relative animazioni:
• sis.bris.ac.uk/~je7796/tech/sort.htm
• www.cs.brockport.edu/cs/javasort.html
In Java, esiste una classe standard che
fornisce quicksort per array di ogni tipo:
• package java.util, classe Arrays
ALGORITMI DI RICERCA
Cercare un elemento in un array:
• in generale, richiede di controllare tutti gli
elementi (fino a che non si trova l’elemento,
o l'array è finito)
• se però l'array è ordinato, la ricerca può
essere svolta in modo molto più efficiente,
sfruttando l’ordinamento per “andare a colpo
sicuro” a cercare l’elemento richiesto.
• metodo sort() (overloaded, molte versioni)
RICERCA BINARIA
• L’algoritmo emula ciò che si fa quando si
cerca, a mano, una parola in un dizionario:
si apre il dizionario “nella prima o nella seconda
metà”, secondo l'iniziale della parola da cercare
• Si confronta l’elemento da cercare con quello di posizione mediana nell’array. Così:
• o l’elemento viene trovato subito
• oppure si sa dove continuare la ricerca
• a sinistra (fra gli elementi minori), se l’elemento
mediano è maggiore di quello richiesto
• a destra (fra gli elementi maggiori) in caso contrario.
RICERCA BINARIA
• La ricerca binaria consente di eliminare ad ogni
passo metà degli elementi del vettore
• Ricerca binaria di un elemento i in un vettore
ordinato in senso non decrescente in cui il primo
elemento è first e l’ultimo last
• Si confronta l’elemento cercato el con quello
mediano del vettore V[med]
• Se el == V[med], fine della ricerca (trovato
= true)
RICERCA BINARIA
1) si confronta l’elemento da cercare con
quello di posizione mediana
2) se è l’elemento cercato, la ricerca si
conclude con successo
-- altrimenti
la ricerca prosegue
• nella metà di sinistra dell’array se l’elemento
mediano è maggiore di quello richiesto
• nella metà di destra dell’array se l’elemento
mediano è minore di quello richiesto.
RICERCA BINARIA
• Altrimenti, se il vettore ha almeno due componenti
(first < last):
– se el < V[med], ripeti la ricerca nella
prima metà del vettore (indici da first a
med-1);
– se el > V[med], ripeti la ricerca nella
seconda metà del vettore (indici da med-1 a
last)
• Numero di confronti: O(log2 N)
3
RICERCA BINARIA
Esempio
4
Scarica