Sei sulla pagina 1di 9

2

Algoritmi di ordinamento

Algoritmi

Ver. 2.4

Lo scopo ordinare in senso [de]crescente il


contenuto di un vettore di N elementi senza
utilizzare un secondo vettore
Esiste molta letteratura scientifica a riguardo
e molti metodi adatti a vari casi, ma qui si
considerano tre semplici algoritmi di esempio
molto per lordinamento in senso crescente (o
meglio, non-decrescente):

Selection sort
Bubble sort
Insertion sort

2010 - Claudio Fornaro - Corso di programmazione in C

Selection sort semplificato - I

Si confronta il primo elemento del vettore con


tutti gli altri, man mano che si trova un valore
minore del primo, lo si scambia con il primo.
Dopo questa operazione il valore minimo
nella prima posizione
il successivo a 0
(pos. 0) del vettore
for (j= 1; j<N; j++)
if (v[j] < v[0])
5 7 5 4 2 6
{
tmp = v[j];
v[j] = v[0];
4 7 5 5 2 6
v[0] = tmp;
}
2 7 5 5 4 6

Selection sort semplificato - II

Se si ripete lo stesso identico procedimento


per tutti gli elementi a partire dal secondo, si
determina il secondo valore pi piccolo e lo si
colloca al secondo posto
il successivo a 1

for (j= 2; j<N; j++)


if (v[j] < v[1])
2 7 5 5 4 6
{
tmp = v[j];
v[j] = v[1];
2 5 7 5 4 6
v[1] = tmp;
}
2 4 7 5 5 6

Selection sort semplificato - III

Se si ripete lo stesso identico procedimento


per tutti gli elementi a partire dalli-esimo, si
determina li-esimo valore pi piccolo e lo si
colloca alli-esimo posto

Selection sort semplificato -IV

il successivo a i

Se si ripete questo procedimento per tutti i


valori di i da 0 fino al penultimo (lultimo va a
posto da s) si ottiene lordinamento in senso
crescente di tutto il vettore
for (i=0; i<N-1; i++)
for (j=i+1; j<N; j++)
if (v[j] < v[i])
{
tmp = v[j];
v[j] = v[i];
v[i] = tmp;
}

for (j=i+1; j<N; j++)


if (v[j] < v[i])
{
tmp = v[j];
v[j] = v[i];
v[i] = tmp;
}

Selection sort - I

Selection sort - II

Il primo passo quello di individuare il


minimo tra gli elementi del vettore e
scambiarlo con quello nella prima posizione,
il primo valore ora al posto giusto
il successivo a 0
jmin = 0;
for (j= 1; j<N; j++)
if (v[j] < v[jmin])
jmin = j;
5 7 5 1 4 3
tmp = v[jmin];
v[jmin] = v[0];
v[0] = tmp;
1 7 5 5 4 3

Se si ripete lo stesso identico procedimento


per tutti gli elementi a partire dal secondo, si
determina il secondo valore pi piccolo e lo si
colloca al secondo posto
il successivo a 1
jmin = 1;
for (j= 2; j<N; j++)
if (v[j] < v[jmin])
jmin = j;
1 7 5 5 4 3
tmp = v[jmin];
v[jmin] = v[1];
v[1] = tmp;
1 3 5 5 4 7

Selection sort - III

10

Selection sort - IV

Se si ripete lo stesso identico procedimento


per tutti gli elementi a partire dalli-esimo, si
determina li-esimo valore pi piccolo e lo si
colloca alli-esimo posto
il successivo a i
jmin = i;
for (j=i+1; j<N; j++)
if (v[j] < v[jmin])
jmin = j;
tmp = v[jmin];
v[jmin] = v[i];
v[i] = tmp;

Se si ripete questo procedimento per tutti i


valori di i da 0 fino al penultimo (lultimo va a
posto da s) si ottiene lordinamento in senso
crescente di tutto il vettore
for (i=0; i<N-1; i++)
{ jmin = i;
for (j=i+1; j<N; j++)
if (v[j] < v[jmin])
jmin = j;
tmp = v[jmin];
v[jmin] = v[i];
v[i] = tmp;
}

11

Bubble sort - I

12

Bubble sort - II

Se si scorrono tutti gli elementi di un vettore


e ogni volta che si trovano due valori
ADIACENTI non in ordine (il pi piccolo dei 2
a destra del pi grande) li si scambia: il pi
grande di tutti risale a destra
3 1 5 7 4 3

for (j=0; j<N-1; j++)


if (v[j] > v[j+1])
1 3 5 7 4 3
{
tmp = v[j];
1 3 5 4 7 3
v[j] = v[j+1];
v[j+1] = tmp;
}
1 3 5 4 3 7

Ripetendo N-1 volte questa operazione, tutti i


valori risalgono verso destra fino ad occupare
la posizione corretta e quindi vengono
ordinati in senso crescente
for (i=0 ; i<N-1; i++)
for (j=0; j<N-1; j++)
if (v[j] > v[j+1])
{
tmp = v[j];
v[j] = v[j+1];
v[j+1] = tmp;
}

13

Bubble sort - III

14

Bubble sort - IV

Inefficienza: gli ultimi valori vengono in ogni


caso confrontati, anche quando sono gi stati
collocati; per evitare perdita di tempo in
questi controlli inutili si ferma prima della fine
il ciclo interno, sfruttando il ciclo esterno
for (i=N-1; i>0 ; i--)
for (j=0; j<i ; j++)
if (v[j] > v[j+1])
{
tmp = v[j];
v[j] = v[j+1];
v[j+1] = tmp;
}

Inefficienza: se pochi valori sono fuori posto e


lordinamento si ottiene prima delle N-1
passate, i cicli continuano ad essere eseguiti.
Lo si fa terminare se non ci sono stati scambi
scambi = SI;
for (i=N-1; i>0 && scambi ;i--)
{ scambi = NO;
for (j=0; j<i ; j++)
continua solo
if (v[j] > v[j+1])
se ci sono
{ scambi = SI;
stati
scambi
tmp = v[j];
v[j] = v[j+1];
v[j+1] = tmp; }
}

15

Insertion sort - I

Insertion sort - II

Per ciascuno degli elementi a partire dal 2o


(lelemento da sistemare si chiama chiave):
si copia il valore della chiave in una variabile (key)
si scalano a destra di una posizione tutti gli
elementi precedenti alla chiave finch non ne
viene trovato uno con valore inferiore a key
4.
al posto di questultimo viene messo key
Notare che gli elementi a sinistra della chiave sono
sempre gi ordinati in senso crescente grazie alle
passate precedenti
3 2
1.

2-3.

1 5 7 3 4 8
key

16

1 3 5 7 4 8

ordinati

for (j=1; j<N; j++)


{
key = v[j];
for (i=j-1; i>=0 && v[i]>key; i--)
v[i+1] = v[i];
v[i+1] = key;
}

17

Esercizi
1.

2.

3.

18

Algoritmi di ricerca

Per ciascuno degli algoritmi di ordinamento


precedentemente descritti (variazioni incluse),
si scriva un programma completo che ordini in
senso crescente (o meglio, non-decrescente)
un vettore di N numeri interi.
Si misurino i tempi di esecuzione usando la
funzione clock() in <time.h>

Si vuole cercare un dato valore val in un


vettore vett di N elementi
Si possono considerare i due casi:

vettore non ordinato


vettore ordinato

Per ciascuno degli algoritmi di ordinamento


precedentemente descritti (variazioni incluse),
si scriva un programma completo che ordini in
senso decrescente (o meglio, noncrescente) un vettore di N numeri interi.

19

20

Ricerca in vettore non ordinato

Ricerca in vettore non ordinato

Si deve scorrere tutto il vettore in quanto val


pu essere in qualsiasi posizione
for (i=0; i<N && vett[i]!=val; i++)
;
if (i == N)
printf("Non trovato\n");
else
printf("Trovato\n");

Il ciclo termina in 2 casi:

Deve stabilire per quale motivo il ciclo finito

Finch non lo trova, continua a cercare

stato trovato il valore


ha finito di cercare (invano) in tutti gli elementi
se trova: i < N
se non lo trova: i = N

Non si deve controllare se val stato trovato


verificando la condizione vett[i]=val
perch se non lo trova i vale N e vett[N]
identifica un elemento inesistente
Al massimo (nel caso peggiore) fa N controlli

Ricerca in vettore ordinato

21

Ricerca lineare

left=0; right=N-1;
while (right>=left)
{ m=(left+right)/2;
if (val==vett[m])
break;
if (val<vett[m])
right=m-1; elimina la met destra
else
left=m+1; elimina la met sinistra
}
if (val==vett[m])
printf("Trovato\n");
else
printf("Non trovato\n");

23

Dicotomica (o binaria)

22

Ricerca dicotomica (o binaria)

Non serve scorrere tutto il vettore, ci si ferma


non appena si supera il valore cercato
for (i=0; i<N && vett[i]<val; i++)
;
if (i<N && val == vett[i])
printf("Trovato\n");
else
printf("Non trovato\n");
Quando vett[i] >= val il ciclo viene
interrotto e si controlla se val stato trovato
Al massimo fa N controlli

Ricerca in vettore ordinato

Ricerca in vettore ordinato

Inizializza due indici left e right al primo e


allultimo indice del vettore (0 e N-1)
Calcola lindice del valore centrale: m
Se vett[m] il valore cercato, termina
Altrimenti se val minore del valore centrale,
arretra lindice destro right al centro m (cos
dimezza il numero di valori in cui cercare)
Altrimenti se val maggiore del valore
centrale, avanza lindice sinistro left al centro
Ripetendo questa operazione, si dimezza ogni
volta il vettore
Veloce: al massimo fa log2(N+1) controlli

24

Programmazione a stati

Per stato si intende la situazione del


programma in un dato istante (es. sta
leggendo i caratteri di una parola)
Mentre il programma viene eseguito esso
cambia di stato in seguito al verificarsi di
eventi (es. lettura di un carattere da
analizzare), la transizione pu portare allo
stesso stato di partenza (anello)

25

Programmazione a stati

Programmazione a stati

Graficamente:

gli stati sono disegnati come cerchi o ovali


le transizioni sono disegnate come archi orientati
nei punti di partenza degli archi si indicano gli
eventi che causano le transizioni di stato
se appropriato (c spazio, non sono troppe
informazioni) sugli archi si indicano anche le azioni
da intraprendere nelle transizioni
azione
evento

azione

Stato1

evento

26

evento

Stato2

azione

Nel codice linformazione sullo stato viene


mantenuta tramite una variabile di stato, in
genere di tipo enum o int
Tipicamente i valori che la variabile di stato
pu assumere sono definiti da enum o con
#define
Se i valori sono costanti e dagli stati partono
diverse possibili transizioni, lo switch
spesso il costrutto di elezione

evento

azione

27

Programmazione a stati

Esempio (es. 4 sui file)


Si scriva un programma che chieda il nome di
un file contenente un testo qualsiasi e di
questo conti quante sono le parole che
iniziano con ciascuna lettera dellalfabeto.
Esempio di output:
Parole che iniziano con A: 45
Parole che iniziano con B: 12
Parole che iniziano con C: 27

Parole che iniziano con Z: 3

28

Programmazione a stati

La variabile di stato indicher se si stanno


leggendo i caratteri di una parola (si dentro
una parola) o no (si fuori da una parola) e
quindi assumer 2 possibili valori:

DENTRO FUORI

Levento che pu causare il cambiamento di


stato la lettura del carattere successivo
In questo esempio ci sono solo 4 casi:

stato
stato
stato
stato

FUORI e si legge un carattere alfabetico


DENTRO e si legge un carattere alfabetico
DENTRO e si legge un carattere non-alfabetico
FUORI e si legge un carattere non-alfabetico

29

Programmazione a stati

Programmazione a stati

Pi in dettaglio, se:

1.

stato FUORI e si legge un carattere alfabetico:


entra DENTRO e incrementa il contatore di quel car.

2.

stato DENTRO e si legge un carattere alfabetico:


resta DENTRO e non fa nulla
stato DENTRO e si legge un carattere non-alfab.:
va FUORI dalla parola e non fa nulla

3.

4.

30

Rappresentazione grafica corrispondente


allesempio (no-op=no operation):
no-op

1.lettera

stato FUORI e si legge un carattere non-alfabetico:


resta FUORI e non fa nulla

incrementa
contatore lettera

FUORI
4.non-lettera no-op

2.lettera

DENTRO
3.non-lettera

no-op

31

Esercizi
3.

Homework 6

(Es. 4 sui file) Si scriva un programma che


chieda il nome di un file contenente un testo
qualsiasi e di questo conti quante sono le
parole che iniziano con ciascuna lettera
dellalfabeto.

Lo si risolva con una soluzione a stati.


Esempio
Parole
Parole
Parole

Parole

32

di output:
che iniziano con A: 45
che iniziano con B: 12
che iniziano con C: 27
che iniziano con Z: 3

Si scriva un programma che per ciascuno degli


algoritmi di ordinamento visti (bubble semplice e
con variazioni, selection semplificato, selection,
insertion) per M volte (es. 100) riempia un
vettore di N valori interi casuali (es. 1000) e lo
riordini. Il programma deve misurare i tempo
impiegato per gli M ordinamenti per ciascuno
degli algoritmi. Impostare M e N in modo da
eseguire un numero significativo di prove con
vettori di dimensioni grandi (1000-10000), medi
(100-1000) e piccoli (100). Trarne le conclusioni.

33

Homework 6
Continuazione:

Includendo <time.h> si possono usare le


seguenti funzioni:
time(NULL)
restituisce un numero intero di tipo time_t che
corrisponde allistante attuale
difftime(time_t t2, time_t t1) restituisce
(come valore double) il numero di secondi
intercorsi tra t1 e t2
Nota: il tipo time_t in genere un sinonimo di long
e si possono definire variabili di tale tipo:
time_t ora, t1, t2;
t1=time(NULL);

Potrebbero piacerti anche