1 / 40

Ordinamento

Ordinamento. Capitolo 24 marzo 2004. 10. 2. 16. 0. -1. 51. 4. 23. 9. 8. ordinamento. -1. 0. 2. 4. 8. 9. 10. 16. 23. 51. Ordinamento di un array. Problema dell’ ordinamento non decrescente di un array sia dati un array di interi

emilia
Download Presentation

Ordinamento

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ordinamento Capitolo 24 marzo 2004 Ordinamento

  2. 10 2 16 0 -1 51 4 23 9 8 ordinamento -1 0 2 4 8 9 10 16 23 51 Ordinamento di un array • Problema dell’ordinamento non decrescente di un array • sia dati un array di interi • trasformare l’array dati in modo tale che gli elementi vi compaiano in ordine non decrescente Ordinamento

  3. Ordinamento di array e API di Java • Come si ordina un array? • package java.util • classe Arrays • metodi di classe void sort(T[] a) • import java.util.Arrays; • ... • int[] dati; // un array di interi • dati = new int[] { 1, 5, 0, 8, 5 }; • /* ora dati vale { 1, 5, 0, 8, 5 } */ • /* ordina dati */ • Arrays.sort(dati); • /* ora dati vale { 0, 1, 5, 5, 8 } */ Ordinamento

  4. Ordinamento per selezione • L’algoritmo di ordinamento per selezione (selection sort) è basato sulla seguente strategia iterativa • finché l’array non è ordinato • seleziona l’elemento di valore minimo dell’array tra quelli che non sono stati ancora ordinati • disponi questo elemento nella sua posizione definitiva Ordinamento

  5. 16 2 51 10 0 -1 16 2 51 10 0 -1 -1 2 51 10 0 16 Strategia dell’ordinamento per selezione • Per prima cosa, l’ordinamento per selezione • determina l’elemento di valore minimo dell’array • l’elemento di valore -1 e indice 5 • tale elemento deve essere collocato nella sua posizione definitiva (posizione 0) • va utilizzato uno scambio Ordinamento

  6. 2 16 2 51 10 0 -1 3 1 temp Scambio di una coppia di elementi dell’array • /* Scambia gli elementi di indice i e j di dati. */ • private static void scambia(int[] dati, int i, int j) { • // pre: dati!=null && 0<= i,j <dati.length • int temp; // variabile di supporto per lo scambio • /* scambia dati[i] con dati[j] */ • temp = dati[i]; • dati[i] = dati[j]; • dati[j] = temp; • } Ordinamento

  7. -1 2 51 10 0 16 -1 2 51 10 0 16 -1 0 51 10 2 16 Strategia dell’ordinamento per selezione • L’ordinamento per selezione prosegue • determina il valore minimo tra gli elementi dell’array che non sono ancora ordinati • colloca questo elemento nella sua posizione definitiva • e così via, finché tutti gli elementi non sono stati ordinati Ordinamento

  8. Strategia dell’ordinamento per selezione • L’algoritmo di ordinamento per selezione • procede per fasi, chiamate passate • gestisce una partizione degli elementi dell’array in due insiemi • elementi ordinati • elementi non ordinati • Nell’ordinamento per selezione • inizialmente, tutti gli elementi sono considerati non ordinati • dopo la prima passata, il primo elemento viene ordinato • per ordinare l’array si devono eseguire tante passate fino a quando tutti gli elementi dell’array non risultano ordinati Ordinamento

  9. 16 2 51 10 0 -1 -1 2 51 10 0 16 -1 0 51 10 2 16 -1 0 2 10 51 16 -1 0 2 10 51 16 -1 0 2 10 16 51 Applicazione dell’ordinamento per selezione Ordinamento

  10. Implementazione dell’ordinamento per selezione • /* Ordina l'array dati in modo non decrescente. • * Ordinamento per selezione. */ • public static void selectionSort(int[] dati) { • // pre: dati!=null • int n; // lunghezza di dati • int i; // indice per la scansione di dati • int ordinati; // numero di elementi ordinati • int imin; // indice dell'elemento di valore • // minimo tra gli elementi • // non ordinati • ... segue ... Ordinamento

  11. Implementazione dell’ordinamento per selezione • /* ordina dati in modo non decrescente • * (ordinamento per selezione) */ • n = dati.length; • /* esegue n-1 passate */ • for (ordinati=0; ordinati<n-1; ordinati++) { • /* gli elementi ordinati sono quelli di indice • * tra 0 (compreso) e ordinati (escluso) */ • /* cerca il minimo tra i non ordinati */ • imin = ordinati; • for (i=ordinati+1; i<n; i++) • if (dati[i]<dati[imin]) • imin = i; • /* ordina l'elemento in imin */ • scambia(dati, ordinati, imin); • /* ora gli elementi ordinati sono quelli di • * indice compreso tra 0 e ordinati (incluso) */ • } • } Ordinamento

  12. Complessità dell’ordinamento per selezione • Complessità asintotica dell’ordinamento per selezione • rispetto alla lunghezza N dell’array da ordinare • operazione dominante • il confronto dati[i]<dati[imin] • caso peggiore • qualunque • contando il numero complessivo di confronti, si può concludere che • TselectionSort(N) = N2 Ordinamento

  13. Ordinamento a bolle • Algoritmo di ordinamento a bolle (bubble sort) • la strategia implementata dall’algoritmo è ancora basata su passate e su confronti e scambi • l’ordinamento a bolle confronta, durante ciascuna passata, tutte le coppie di elementi adiacenti tra gli elementi non ordinati dell’array Ordinamento

  14. 10 2 0 16 51 -1 2 10 0 16 51 -1 2 0 10 16 51 -1 2 0 10 16 51 -1 2 0 10 16 51 -1 2 0 10 16 -1 51 Una passata dell’ordinamento a bolle Ordinamento

  15. 10 2 0 16 51 -1 2 0 10 16 -1 51 0 2 10 -1 16 51 0 2 -1 10 16 51 0 -1 2 10 16 51 -1 0 2 10 16 51 Applicazione completa dell’ordinamento a bolle Ordinamento

  16. Implementazione elementare dell’ordinamento a bolle • /* Ordina l'array dati in modo non decrescente. • * Ordinamento a bolle -- versione elementare. */ • public static void simpleBubbleSort(int[] dati) { • // pre: dati!=null • int n; // lunghezza di dati • int i; // indice per la scansione di dati • int ordinati; // numero di elementi ordinati • ... segue ... Ordinamento

  17. Implementazione elementare dell’ordinamento a bolle • /* ordina dati in modo non decrescente • * (ordinamento a bolle -- versione elementare) */ • n = dati.length; • /* esegue n-1 passate */ • for (ordinati=0; ordinati<n-1; ordinati++) { • /* gli elementi ordinati sono quelli di indice • * tra n-ordinati (compreso) e n (escluso) */ • /* confronta ogni elemento non ordinato • * con quello che lo precede • * (ed eventualmente li scambia) */ • for (i=1; i<n-ordinati; i++) • if (dati[i]<dati[i-1]) • scambia(dati, i, i-1); • /* ora gli elementi ordinati sono quelli di • * indice tra n-ordinati-1 (compreso) • * e n (escluso) */ • } • } Ordinamento

  18. 0 2 16 -1 10 51 0 2 -1 10 16 51 Considerazioni per migliorare l’ordinamento a bolle • Una passata dell’ordinamento a bolle può portare nella posizione definitiva più di un elemento Ordinamento

  19. -1 0 2 10 16 51 -1 0 2 10 16 51 Considerazioni per migliorare l’ordinamento a bolle • È possibile che in una passata dell’ordinamento a bolle non avvengano scambi Ordinamento

  20. -1 2 16 0 10 51 -1 2 0 10 16 51 -1 0 2 10 16 51 -1 0 2 10 16 51 Applicazione dell’ordinamento a bolle Ordinamento

  21. Implementazione dell’ordinamento a bolle • /* Ordina l'array dati in modo non decrescente. • * Ordinamento a bolle. */ • public static void bubbleSort(int[] dati) { • // pre: dati!=null • int n; // lunghezza di dati • int i; // indice per la scansione di dati • int ordinati; // numero di elementi ordinati • int ultimoScambio; // posizione in cui è avvenuto • // l'ultimo scambio durante la • // passata corrente • /* ultimoScambio vale 0 se non sono stati ancora • * eseguiti scambi durante la passata corrente */ • ... segue ... Ordinamento

  22. Implementazione dell’ordinamento a bolle • /* ordina dati in modo non decrescente • * (ordinamento a bolle) */ • n = dati.length; • ordinati = 0; • /* esegue passate finché dati non è ordinato */ • while (ordinati<n-1) { • /* gli elementi ordinati sono quelli di indice • * tra n-ordinati (compreso) e n (escluso) */ • /* confronta ogni elemento non ordinato • * con quello che lo precede */ • ultimoScambio = 0; • for (i=1; i<n-ordinati; i++) • if (dati[i]<dati[i-1]) { • scambia(dati, i, i-1); • ultimoScambio = i; • } • /* ora gli elementi ordinati sono quelli di • * indice tra ultimoScambio e n */ • ordinati = n-ultimoScambio; • } • } Ordinamento

  23. Complessità dell’ordinamento a bolle • Complessità asintotica dell’ordinamento a bolle • rispetto alla lunghezza N dell’array da ordinare • operazione dominante • il confronto dati[i]<dati[i-1] • caso peggiore • l’array è ordinato in modo decrescente • il numero complessivo di confronti è quadratico • TbubbleSort(N) = N2 Ordinamento

  24. Ordinamento per inserzione • Algoritmo di ordinamento per inserzione (insertion sort) • gli elementi sono partizionati in due insiemi • elementi relativamente ordinati • elementi non relativamente ordinati • inizialmente viene considerato relativamente ordinato il primo elemento dell’array • ad ogni passata • colloca il primo tra gli elementi non relativamente ordinati tra quelli relativamente ordinati Ordinamento

  25. -1 10 16 0 51 2 3 2 -1 0 10 16 51 2 -1 10 16 0 51 2 4 1 Una passata dell’ordinamento per inserzione • Effetto di una passata dell’ordinamento per inserzione • Dinamica dell’inserimento Ordinamento

  26. 10 -1 16 0 51 2 -1 10 16 0 51 2 -1 10 16 0 51 2 -1 0 10 16 51 2 -1 0 10 16 51 2 -1 0 2 10 16 51 Applicazione completa dell’ordinamento per inserzione Ordinamento

  27. Implementazione dell’ordinamento per inserzione • /* Ordina l'array dati in modo non decrescente. • * Ordinamento per inserzione. */ • public static void insertionSort(int[] dati) { • // pre: dati!=null • int n; // lunghezza di dati • int i; // indice per la scansione di dati • int ordinati; // numero di elementi • // "relativamente ordinati" • int corrente; // elemento da "ordinare" • boolean ins; // è possibile inserire corrente • // tra gli "relativamente ordinati" • ... segue ... Ordinamento

  28. Implementazione dell’ordinamento per inserzione • /* ordina dati in modo non decrescente • * (ordinamento per inserzione) */ • n = dati.length; • /* esegue n-1 passate */ • for (ordinati=1; ordinati<n; ordinati++) { • /* gli elementi "relativamente ordinati" sono • * quelli di indice tra 0 e ordinati */ • /* viene "ordinato" il primo elemento • * tra i "non relativamente ordinati" */ • corrente = dati[ordinati]; • ins = false; • i = ordinati; • while (!ins && i>0) • if (corrente<dati[i-1]) { // sposta verso dx • dati[i] = dati[i-1]; • i--; • } else • ins = true; • /* inserisce corrente tra i "rel. ordinati" */ • dati[i] = corrente; • /* ora gli elementi "rel. ordinati" sono quelli • * di indice compreso tra 0 e ordinati */ • } • } Ordinamento

  29. Complessità dell’ordinamento per inserzione • Complessità asintotica dell’ordinamento per inserzione • rispetto alla lunghezza N dell’array da ordinare • operazione dominante • il confronto corrente<dati[i-1] • caso peggiore • l’array è ordinato in modo decrescente • il numero complessivo di confronti è quadratico • TinsertionSort(N) = N2 Ordinamento

  30. Ordinamento per fusione • Algoritmo di ordinamento per fusione (merge sort) per ordinare una sequenza • se la sequenza da ordinare contiene uno o due elementi, allora la sequenza viene ordinata direttamente • se invece la sequenza da ordinare contiene più di due elementi, allora • gli elementi della sequenza vengono partizionati in due sotto-sequenze • le due sotto-sequenze vengono ordinate separatamente • le due sotto-sequenze ordinate vengono fuse in un’unica sequenza ordinata Ordinamento

  31. 85 24 63 45 17 31 96 50 decomposizione 85 24 63 45 17 31 96 50 ordinamento 24 45 63 85 17 31 50 96 fusione 17 24 31 45 50 63 85 96 Strategia dell’ordinamento per fusione Ordinamento

  32. 85 24 63 45 17 31 96 50 decomposizioni 85 24 63 45 17 31 96 50 85 24 63 45 17 31 96 50 ordinamenti (semplici) 24 85 45 63 17 31 50 96 24 45 63 85 17 31 50 96 fusioni 17 24 31 45 50 63 85 96 Strategia ricorsiva dell’ordinamento per fusione Ordinamento

  33. Implementazione dell’ordinamento per fusione • L’algoritmo di ordinamento per fusione può essere implementato utilizzando tre metodi • void mergeSort(int[] dati) • mergeSortRic • merge • Considerazioni • per motivi di efficienza, i tre metodi utilizzano un array di appoggio temp condiviso da tutte le attivazioni Ordinamento

  34. Implementazione dell’ordinamento per fusione • /* Ordinamento l'array dati in modo non decrescente. • * Ordinamento per fusione. */ • public static void mergeSort(int[] dati) { • // pre: dati!=null • int n; // lunghezza di dati • /* ordina dati in modo non decrescente */ • n = dati.length; • /* avvia la ricorsione: • * ordina dati, • * dall'elemento di posizione 0 (compreso) • * a quello di posizione n (escluso) • * usando un array di appoggio di lunghezza n */ • mergeSortRic(dati, 0, n, new int[n]); • } Ordinamento

  35. Implementazione dell’ordinamento per fusione • /* Ordina gli elementi di dati tra sinistra (incluso) e • * destra (escluso) usando l'array di appoggio temp. */ • private static void mergeSortRic(int[] dati, • int sinistra, int destra, int[] temp) { • int m; // numero di elementi da ordinare • int centro; // indice dell'elemento centrale • // della sottosequenza da ordinare • /* ordina gli elementi di dati tra sinistra • * (incluso) e destra (escluso) */ • m = destra-sinistra; • if (m==2) { // caso base, confronto e scambio • if (dati[sinistra]>dati[destra-1]) • scambia(dati, sinistra, destra-1); • } else if (m>2) { // caso ricorsivo • centro = (sinistra+destra)/2; • mergeSortRic(dati, sinistra, centro, temp); • mergeSortRic(dati, centro, destra, temp); • merge(dati, sinistra, centro, destra, temp); • } • /* m<2 è un altro caso base, la sottosequenza è • * già ordinata */ • } Ordinamento

  36. Complessità dell’ordinamento per fusione • Complessità asintotica dell’ordinamento per fusione • discussa in modo informale • rispetto alla lunghezza N dell’array da ordinare • attività dominante • fusione di sottosequenze ordinate • caso peggiore • qualunque Ordinamento

  37. 24 85 45 63 17 31 50 96 24 45 63 85 17 31 50 96 fusioni 17 24 31 45 50 63 85 96 Complessità dell’ordinamento per fusione • un certo numero di livelli di decomposizioni e fusioni • in ciascun livello vengono fusi tutti gli elementi • il costo asintotico di ciascun livello di fusioni è N • il numero di livelli è log2 N • TmergeSort(N) = N log N Ordinamento

  38. 58 65 67 45 31 16 96 50 50 16 31 45 58 67 96 65 45 16 31 50 65 67 96 31 16 45 65 96 16 31 45 50 58 65 67 96 Ordinamento veloce • L’algoritmo di ordinamento di array più usato in pratica è l’ordinamento veloce (quick sort) Ordinamento

  39. Complessità dell’ordinamento veloce • È stato dimostrato l’ordinamento veloce ha, nel caso peggiore, complessità asintotica quadratica rispetto alla lunghezza dell’array da ordinare • tuttavia, l’ordinamento veloce viene solitamente preferito all’ordinamento per fusione • perché? Ordinamento

  40. Risultati sperimentali • Tempi medi di esecuzione, in secondi N Algoritmo 1 000 10 000 100 000 1 000 000 selection sort 0.02 0.27 24.05 circa 40 minuti bubble sort elementare 0.01 0.66 62.35 circa 100 minuti bubble sort 0.02 0.67 62.20 circa 100 minuti bubble sort bidirezionale 0.01 0.47 43.25 circa 70 minuti insertion sort 0.01 0.23 18.80 circa 30 minuti merge sort 0.01 0.01 0.05 0.51 quick sort (API di Java) 0.01 0.02 0.05 0.35 Ordinamento

More Related