Top Banner
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
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

Feb 28, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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;}