Divide et Impera Quicksort Mergesort -...

23
1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare (Prof. Emerito alla Oxford University) Computer Jurnal 5,1,1962 John von Neumann(1903-1957) Nel 1944, il suo rapporto interno “First Draft of a Report on the EDVAC” contiene tra l’altro, il mergesort come programma di ordinamento

Transcript of Divide et Impera Quicksort Mergesort -...

Page 1: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

1

Divide et Impera

Quicksort MergesortCharles Antony Richard Hoare(Prof. Emerito allaOxford University) Computer Jurnal 5,1,1962

John von Neumann(1903-1957)Nel 1944, il suo rapporto interno“First Draft of a Report on theEDVAC” contiene tra l’altro, ilmergesort come programma diordinamento

Page 2: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

2

MergeSort

•Esempio di algoritmo basato su Divide et Impera

•Due fasi:•Fase di suddivisione

•Divide il lavoro a metà•Fase di ordinamento (fusione)

•Impera sulle due metà!

Page 3: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

3

MergeSort

• Dividi– Dividi la lista in due metà

Metà sinistra Metà destra

Page 4: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

4

MergeSort

• Impera1 Applica lo stesso algoritmo a ogni metà

Nuove chiamate

Metà sinistra Metà destra

Page 5: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

5

MergeSort

• Impera2 (a partire da quando si ha un solo elemento o

nessuno)fondi

fondi

Metà sinistra ordinata Metà destra ordinata

Page 6: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

6

2 3 7 4 9 1 5 0

2 3 7 4 9 1 5 0

2 3 7 4 9 1 5 0

2 3 7 4 9 1 5 0

3 4 7 1 9 0 5

2 3 4 7 0 1 5 9

0 1 2 3 4 5 7 9

Dividi

Dividi

Dividi

fondi

fondi

fondi

2

Page 7: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

7

if “ci sono almeno due elementi da ordinare”

{1. dividi la lista in due metà.

2. chiamata ricorsiva di mergesort per la prima metà .

3. chiamata ricorsiva di mergesort per la seconda metà.

4. fusione (quindi ordinamento) delle due metà ordinate. }

Pseudocodice per il mergesort

Page 8: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

8

Implementazione su una lista concatenata L:

if (L) /* la lista non è vuota. */

{If (L-> next) { 1. dividi la lista in due metà. /* costo lineare */

2. chiamata ricorsiva di mergesort per la prima metà .

3. chiamata ricorsiva di mergesort per la seconda metà.

4. fusione (merging) delle due metà ordinate. } /* costo lineare, opera in loco */ }

Page 9: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

9

Implementazione su liste concatenate, due modi didividere una lista in due sottoliste di circa ugualelunghezza:Idea 1:Si spostano ricorsivamente gli elementi di posto pariin una nuova lista, lasciando quelli di posto dispari inquella originaria:

Idea 2:Si usano due puntatori per scorrere la lista, unoavanza di un record alla volta e l’altro di due,quando il secondo ha raggiunto la fine della lista, ilprimo puntatore è usato come puntatore inizialedella seconda metà lista.

Page 10: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

10

Implementazione su un vettore di n elementi:

if (n>1) /* ci sono almeno due elementi. */ {1. Dividi il vettore in due metà. /*Facile costo costante */

2. chiamata ricorsiva di mergesort per la prima metà .

3. chiamata ricorsiva di mergesort per la seconda metà.

4. fusione (merging) delle due metà ordinate /* necessita di un vettore di appoggio */ }

Page 11: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

11

void mergeSort (int *v,int* app,int start, int end)/* ordina, in modo crescente, il vettore v*postc: v[i]<=v[i+1], per start <=i<end*/

{ int middle; if (start < end) /* ci sono almeno 2 elementi */

{ middle = (start + end) / 2; /* calcola il punto mediano */

mergeSort (v,app,start, middle); /* ordina la prima metà */

mergeSort (v,app,middle, end); /* ordina la seconda metà */

merge (v, app,start, middle, end); /* fonde le due metà ordinate */ }}

Implementazione su vettori:

Page 12: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

12

void merge(int * v, int * app,int start, int middle, int end)/* fonde i sottovettori v[start..middle] e v[middle..end], restituendo il risultato in v.*prec: v[i]<=v[i+1] per start <= i < middle e * v[j]<=v[j+1] per middle +1 <= j < end postc: v[i]<=v[i+1] per start <= i < end */*/{int k = start , i = middle +1 ,j = start;/* k è l'indice di scorrimento della prima metà, idella seconda, j del vettore d’appoggio app */while ((k <= middle) && (i <= end)) /*ciclo 1*/ { if (v[k] <= v[i])   {app[j] = v[k]; k = k+1;} else   {app[j] = v[i]; i = i+1;}  j = j+1; } if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo 1, bisogna aggiungere incoda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; k = k+1; j = j+1}  while (j <= end);/* l'uscita dal ciclo 1 si è avuta per (k > middle): gli elementi v[p],...,v[end] sono già alposto giusto, quindi si ricopia solo app in v */ for (k = start;k < j; k++) v[k] = app[k];}

Page 13: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

13

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

100 1 2 3 4 5 6 7

k i

j

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

k i

Chiamata merge(v,app,0,3, 7); uscita (i > end)

while ((k <= middle) && (i <= end))/*ciclo 1*/ { if (v[k]<=v[i])   {app[j] = v[k]; k = k+1;} else   {app[j] = v[i]; i = i+1;}  j = j+1; }  if (k <= middle) /* (i > end) haprovocato l'uscita dal while, bisognaaggiungere in coda gli ultimi elementinella prima metà */ do {app[j] = v[k]; k = k+1; j = j+1}  while (j <= end);

v=

app=

v=

Page 14: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

14

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

10 200 1 2 3 4 5 6 7

k i

j

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

k i

Chiamata merge(v,app,0,3, 7); uscita (i > end)

v=

app=

v=

while ((k <= middle) && (i <= end))/*ciclo 1*/ { if (v[k] <= v[i])   {app[j] = v[k]; k = k+1;} else   {app[j] = v[i]; i = i+1;}  j = j+1; }  if (k <= middle) /* (i > end) haprovocato l'uscita dal while, bisognaaggiungere in coda gli ultimi elementinella prima metà */ do {app[j] = v[k]; k = k+1; j = j+1}  while (j <= end);

Page 15: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

15

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

10 20 300 1 2 3 4 5 6 7

k i

j

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

k i

Chiamata merge(v,app,0,3, 7); uscita (i > end)

v=

app=

v=

while ((k <= middle) && (i <= end))/*ciclo 1*/ { if (v[k] <= v[i])   {app[j] = v[k]; k = k+1;} else   {app[j] = v[i]; i = i+1;}  j = j+1; }  if (k <= middle) /* (i > end) haprovocato l'uscita dal while, bisognaaggiungere in coda gli ultimi elementinella prima metà */ do {app[j] = v[k]; k = k+1; j = j+1}  while (j <= end);

Page 16: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

16

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

10 20 30 400 1 2 3 4 5 6 7

k i

j

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

k i

Chiamata merge(v,app,0,3, 7); uscita (i > end)

v=

app=

v=

while ((k <= middle) && (i <= end))/*ciclo 1*/ { if (v[k] <= v[i])   {app[j] = v[k]; k = k+1;} else   {app[j] = v[i]; i = i+1;}  j = j+1; }  if (k <= middle) /* (i > end) haprovocato l'uscita dal while, bisognaaggiungere in coda gli ultimi elementinella prima metà */ do {app[j] = v[k]; k = k+1; j = j+1}  while (j <= end);

Page 17: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

17

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

10 20 30 400 1 2 3 4 5 6 7

60

k i

j

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

k i

Chiamata merge(v,app,0,3, 7); uscita (i > end)

v=

app=

v=

while ((k <= middle) && (i <= end))/*ciclo 1*/ { if (v[k] <= v[i])   {app[j] = v[k]; k = k+1;} else   {app[j] = v[i]; i = i+1;}  j = j+1; }  if (k <= middle) /* (i > end) haprovocato l'uscita dal while, bisognaaggiungere in coda gli ultimi elementinella prima metà */ do {app[j] = v[k]; k = k+1; j = j+1}  while (j <= end);

Page 18: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

18

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

10 20 30 400 1 2 3 4 5 6 7

60 70

k i

j

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

k i

Chiamata merge(v,app,0,3, 7); uscita (i > end)

v=

app=

v=

while ((k <= middle) && (i <= end))/*ciclo 1*/ { if (v[k] <= v[i])   {app[j] = v[k]; k = k+1;} else   {app[j] = v[i]; i = i+1;}  j = j+1; }  if (k <= middle) /* (i > end) haprovocato l'uscita dal while, bisognaaggiungere in coda gli ultimi elementinella prima metà */ do {app[j] = v[k]; k = k+1; j = j+1}  while (j <= end);

Page 19: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

19

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

10 20 30 400 1 2 3 4 5 6 7

60 70 80 90

k i

j

20 40 80 900 1 2 3 4 5 6 7

10 30 60 70

ki

Chiamata merge(v,app,0,3, 7); uscita (i > end)

v=

app=

v=

 if (k <= middle) /* (i > end) haprovocato l'uscita dal while, bisognaaggiungere in coda gli ultimi elementinella prima metà */ do {app[j] = v[k]; k = k+1; j = j+1}  while (j <= end);

Page 20: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

20

20 50 60 700 1 2 3 4 5 6 7

10 30 80 90

10 20 30 500 1 2 3 4 5 6 7

60 70

k i

j

10 20 30 500 1 2 3 4 5 6 7

60 70 80 90

k i

Chiamata merge(v,app,0,3, 7);uscita (k > middle)

v=

app=

v=

k> middle

while ((k <= middle) && (i <= end))/*ciclo 1*/ { if (v[k] <= v[i])   {app[j] = v[k]; k = k+1;} else   {app[j] = v[i]; i = i+1;}  j = j+1; }  if (k <= middle) /* (i > end) haprovocato l'uscita dal while, bisognaaggiungere in coda gli ultimi elementinella prima metà */ do {app[j] = v[k]; k = k+1; j = j+1}  while (j <= end);  for (k = start;k < j; k++) v[k] = app[k];

Page 21: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

21

int verificaOrd(int *a, const int n) /* controlla se il vettore è ordinato * postc: dà 1 se v[i]<= v[i+1] per 0 <= i < n-1 e 0 altrimenti */ {int i; for(i=0;i< n-1;i++) if (a[i] > a[i+1]) return 0; return 1; }

void inVett(int* vett, int num)/*inizializza un vettore con num interi pseudocasuali*/{srand(time(NULL));printf("Inizializziamo un vettore\n");for (i = 0;i < num;i++) vett[i] = rand() ;return vett;}

Page 22: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

22

main(){int num, j,numTest;int* app,* vett;printf("Inserisci il numero di test da effettuare.\n");scanf("%d",&numTest);for (j=0;j<numTest;j++)

{printf("Inserisci il numero di elementi del vettore.\n");scanf("%d",&num);vett = (int*)malloc(num*sizeof(int));app = (int*)malloc(num*sizeof(int));inVett(vett,num);printf("Gli elementi scelti a caso e inseriti nel vettore sono:\n");stVett(vett,num);mergeSort(vett,app,0,num-1);assert(verificaOrd(vett,num));printf("Gli elementi ordinati nel vettore sono:\n");stVett(vett,num);printf("Tutto bene con il mergeSort.\n");}

return 0;}

Page 23: Divide et Impera Quicksort Mergesort - uniroma1.ittwiki.di.uniroma1.it/pub/Programmazione2ad/WebHome/MergesortInt.pdf1 Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

23

ListeStrP divMeta(ListeStrP lista){ListeStrP app;if (!lista || !(lista->nextPtr)) return NULL;app = lista -> nextPtr;lista -> nextPtr = app ->nextPtr;app->nextPtr = divMeta(app ->nextPtr);return app;}