Laboratorio di Programmazione
Appunti sulla lezione 4:
Divide et impera e algoritmi di ordinamento
Alessandra Raffaetà
Università Ca’ Foscari Venezia
Corso di Laurea in Informatica
Ricerca binaria
ƒ Assunzione: l’array v è ordinato.
ƒ Ricerca binaria: Si confronta l’elemento x da
cercare con l’elemento m in posizione centrale
dell’array v.
□ Se x è uguale a m ho finito.
□ Se x è minore di m, la ricerca prosegue nella metà
inferiore dell’array.
□ Se x è maggiore di m, la ricerca prosegue nella metà
superiore dell’array.
Il processo prosegue fino al reperimento di x
oppure fino all’esaurimento dell’array nel qual
caso x non è presente in v.
1
Algoritmo per la ricerca binaria
int ricercabinaria (TipoElem v[ ], TipoElem elem, int inf, int sup)
{ int med, indice;
if (inf > sup)
/*la parte del vettore fra inf e sup è vuota */
indice = -1;
else {
med = (inf + sup)/2;
if (equal(elem, v[med]))
indice = med;
/*l’elemento è stato trovato */
else
if (minore(elem, v[med]))
/*cerca nella parte inferiore*/
indice = ricercabinaria(v, elem, inf, med -1);
else
/*cerca nella parte superiore*/
indice = ricercabinaria(v, elem, med+1, sup);
}
return indice;
}
ƒ Chiamata della funzione: risultato = ricercabinaria(v, elem, 0, dim–1);
Esempio di ricerca binaria
Dato il vettore v ordinato, determinare l’indice di 51 se occorre in v.
v
7
25
33
51
55
60
0
1
2
3
4
5
7
25
33
51
55
60
0
1
2
3
4
5
51
3
51
55
4
60
med = 2
med = 4
5
med = 3
3
L’elemento è stato trovato e la sua posizione in v è 3.
2
Tecnica di progetto di algoritmi: divide et impera
Soluzione ricorsiva di un problema articolata in 3
passi:
ƒ Divide: divisione del problema originale in sottoproblemi
analoghi a quello originale, ma di dimensione inferiore.
ƒ Impera: soluzione ricorsiva dei sottoproblemi; se la
dimensione dei sottoproblemi è sufficientemente piccola,
questi possono essere risolti direttamente.
ƒ Combina: composizione delle soluzioni dei sottoproblemi
per ottenere una soluzione del problema originale.
Esempio di tecnica divide et impera
ƒ Problema: Trovare il minimo elemento di un array non
vuoto.
ƒ Divide: divide l’array A[inf..sup] in due
sottoarray con metà elementi, A[inf..med] e
A[med+1..sup] dove med = (inf+sup)/2.
ƒ Impera: trova i min applicando la funzione
ricorsivamente ai sottoarray se il sottoarray ha
almeno due elementi, altrimenti il min è
l’elemento stesso.
ƒ Combina: confronta i due min trovati di
A[inf..med] e A[med+1..sup] e restituisce il min
dei due al fine di ottenere il min di A[inf..sup].
3
Funzione massimo – divide et impera
int minimo (int v[ ], int inf, int sup)
/*Trova il minimo degli elementi di v di indice compreso tra inf e sup */
{ int m1, m2, med;
if (inf == sup)
/* impera: risolve direttamente */
return v[inf];
/* divide: il problema in 2 sottopb */
med = (inf + sup)/2;
m1 = minimo(v, inf, med);
/*impera: trova min parte inferiore*/
m2 = minimo(v, med + 1, sup); /*impera:trova min partesuperiore*/
if (m1 < m2)
/*combina: trova min del vettore*/
return m1;
return m2;
}
Funzione conta – divide et impera
ƒ Problema: Sommare gli elementi di un vettore non
vuoto.
int conta (int v[ ], int inf, int sup)
/*restituisce la somma degli elementi nel vettore v nella
porzione di array fra inf e sup */
{ int med;
if (inf == sup)
return v[inf];
med = (inf + sup)/2;
return conta(v, inf, med) + conta(v, med+1, sup);
}
4
Problema dell’ordinamento
ƒ Input: sequenza di N elementi <a1, …, aN>
ƒ Output: permutazione <ai1,…, aiN> tale che se
k < h allora minore(ak,ah).
ƒ Algoritmi basati sul confronto:
□ Insertion sort.
□ Selection sort.
□ Bubble sort.
□ Merge sort.
Insertion sort
ƒ Algoritmo di tipo incrementale.
ƒ Idea: ordinamento delle carte da gioco. Partendo con la
mano sinistra vuota e le carte sul tavolo, si preleva una
carta alla volta dal tavolo e si inserisce in posizione
corretta nella mano sinistra (cioè mantenendo le carte
in mano ordinate).
ordinata
?
i
ordinata
?
Si inserisce nel
sottoarray ordinato
[0..i-1] l’elemento di
indice i mantenendo
ordinato il
sottoarray [0..i]
5
Insertion sort
void insertionSort (TipoElem v[ ], int dim)
{ int ind_sist,
/* indice del prox elemento da sistemare */
ind_contr;
/* indice dell’elemento da controllare */
TipoElem val_sist; /* valore dell’elemento da sistemare */
for (ind_sist = 0; ind_sist < dim – 1; ind_sist++){
val_sist = v[ind_sist + 1];
/* controlla e sposta gli elem partendo dall’ultimo elem sistemato */
}
}
ind_contr = ind_sist;
while (ind_contr >= 0 && maggiore(v[ind_contr], val_sist)) {
v[ind_contr + 1] = v[ind_contr];
ind_contr --;
}
v[ind_contr + 1] = val_sist;
Selection sort
ƒ Idea: estrazioni successive del minimo.
ƒ Si cerca il più piccolo elemento dell’array e lo si
scambia con l’elemento di indice 0, quindi si
cerca in [1..dim-1] il più piccolo e lo si scambia
con l’elemento di indice 1 e così via.
ordinata
v
a
l
m
i
n
ordinata
m
i
n
v
a
l
6
Selection sort
void selectionSort (TipoElem v[ ], int dim)
/* indice elemento minimo */
{ int i, j, i_min;
TipoElem temp;
for (i = 0; i < dim – 1; i++){
/* ricerca indice elemento minimo in v[i..dim-1] */
i_min = i;
for (j = i+1; j < dim; j++)
if (minore(v[j], v[i_min])
i_min = j;
if (i != i_min)
swap(v, i, i_min);
}
}
7