Scoperta guidata di tipici algoritmi: selection sort, bubble sort ….

Slides:



Advertisements
Presentazioni simili
Algoritmi di ordinamento
Advertisements

INFORMATICA Algoritmi fondamentali
Algoritmi notevoli In linguaggio C.
Capitolo 4 Ordinamento: Selection e Insertion Sort Algoritmi e Strutture Dati.
Capitolo 4 Ordinamento: Selection e Insertion Sort Algoritmi e Strutture Dati.
Capitolo 4 Ordinamento: Selection e Insertion Sort Algoritmi e Strutture Dati.
Ordinamento di una lista: bubble-sort
Algoritmi e Strutture Dati III. Algoritmi di Ordinamento
QuickSort Quick-Sort(A,s,d) IF s < d THEN q = Partiziona(A,s,d) Quick-Sort(A,s,q-1) Quick-Sort(A,q + 1,d)
Algoritmi di Ordinamento
Algoritmi CHE COS’è UN ALGORITMO di ORDINAMENTO?
ALGORITMI Un algoritmo è un insieme di istruzioni: -ordinate -non ambigue -effettivamente computabili.
ALGORITMO Un algoritmo è un procedimento che risolve un determinato problema attraverso un numero finito di passi. Un formalismo che permette di rappresentare.
Soluzione 6: Algoritmo Quicksort
Algoritmi e Strutture Dati
Paola Disisto, Erika Griffini, Yris Noriega.  Insieme ordinato di operazioni non ambigue ed effettivamente computabili che, quando eseguito, produce.
CORSO DI PROGRAMMAZIONE II
Esercitazione sull’ ordinamento 20 maggio 2003
Problema dell’Ordinamento. Problema dell’ordinamento Formulazione del problema –Si vuole ordinare una lista di elementi secondo una data proprietà P Esempio:
GLI ALGORITMI DI ORDINAMENTO
Quick sort void quick_sort (int a[],int l, int r) { int i, j,v, t; if (r>l) { v=a[r];//L’elemento “pivot” è quello più a dx i=l-1; j=r; // i scorre da.
L’ALGORITMO Un algoritmo è un procedimento formale che risolve un determinato problema attraverso un numero finito di passi. Un problema risolvibile mediante.
30/10/01Array 1  Un array e’ una struttura dati che contiene piu’ valori del medesimo tipo.  La lunghezza di un array e’ stabilita quando l’array viene.
6/11/01Ordinamento 1 Un esempio di algoritmi: ordinamento.
Huffman Canonico: approfondimento. Come abbiamo visto, Huffman canonico ci permette di ottenere una decompressione più veloce e con un uso più efficiente.
1 ELEMENTI DI INFORMATICA Università degli Studi di Cagliari Corso di Laurea in Ingegneria Elettronica Linguaggio C A.A. 2011/2012
Fondamenti di Informatica A - Massimo Bertozzi LE RAPPRESENTAZIONI CONCATENATE.
Ereditarietà Uno dei principi della programmazione orientata agli oggetti (OOP) è il riuso Le classi dovrebbero essere progettate come componenti riutilizzabili.
© 2007 SEI-Società Editrice Internazionale, Apogeo
Algoritmi su Array Moreno Marzolla
Algoritmi Avanzati a.a.2014/2015 Prof.ssa Rossella Petreschi
Progettare algoritmi veloci usando strutture dati efficienti
Progettare algoritmi veloci usando strutture dati efficienti
Ordinamento.
Algoritmi Avanzati a.a.2010/2011 Prof.ssa Rossella Petreschi
10. Programmazione Ricorsiva Ing. Simona Colucci
9. Problemi ricorrenti: ordinamento e ricerca
Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare
Approcci nella soluzione di un problema
Tipo di dato: array Un array è un tipo di dato usato per memorizzare una collezione di variabili dello stesso tipo. Per memorizzare una collezione di 7.
8b. Esempi di algoritmi con l’uso di array: ordinamento e ricerca
Algoritmi e Strutture Dati
Divide et Impera Quicksort Mergesort
Quick Sort: Esempio Si consideri il seguente vettore, v, di n=10 elementi: i=inf j=sup Scegliamo come pivot.
Java World Cicli e Array.
Corso Java Cicli e Array.
iterazione o ricorsione nel pensare per OGGETTI
© 2007 SEI-Società Editrice Internazionale, Apogeo
Oggetti Java.
Scrivere programmi corretti
Ordinamento in tempo lineare
Sommario cos’è un tipo di dato astratto astrazione tramite specifica:
Fondamenti di Informatica
Ricorsione 16/01/2019 package.
© 2007 SEI-Società Editrice Internazionale, Apogeo
Algoritmo InsertionSort
APPUNTI SUL LINGUAGGIO C
Algoritmi e Strutture Dati
Corso di Laurea Ingegneria Informatica Fondamenti di Informatica
Corso di Laurea Ingegneria Informatica Fondamenti di Informatica
Progettare algoritmi veloci usando strutture dati efficienti
APPUNTI SUL LINGUAGGIO C
* 07/16/96 Sez. 2: Ordinamento La consultazione di banche dati è sempre più cruciale in tutte le applicazioni dell’Informatica. Se vogliamo consultare.
APPUNTI SUL LINGUAGGIO C Esercizi sugli array e strutture
MergeSort Usa la tecnica del divide et impera:
concetti ed applicazioni
Dalla programmazione tradizionale al paradigma OO
Ricerca 01/08/2019 package.
HeapSort Stesso approccio incrementale del selectionSort Tipo di dato
Algoritmi di ordinamento
Transcript della presentazione:

Scoperta guidata di tipici algoritmi: selection sort, bubble sort …. Ordinamento Scoperta guidata di tipici algoritmi: selection sort, bubble sort ….

Problema stimolo Si possiede una bilancia a due piatti ed N sacchi di iuta pieni di caffè. Ciascun sacco è identificato da una lettera dell'alfabeto (A , B, C, D …). ... Lo scopo che si vuole raggiungere è ordinarli rispetto al peso in modo che su una lavagna compaia un elenco dove la lettera che identifica il sacco più pesante sia seguita dalle lettere che identificano i sacchi di peso via via decrescente.

Azioni possibili Le attività che si possono eseguire sono: - vuotare sacco - annotare su lavagna una lettera - prendere sacco e metterlo su un piatto della bilancia - riporre sacco - scambiare piatto al sacco

Domande che possiamo porci Le domande che possiamo porci: - se un sacco pesa più di un altro - se tutti i sacchi sono vuoti - se ho finito il confronto tra sacchi  

Ordinamento per massimi successivi

Ordinamento per massimi successivi public class Sacchi { private double sacchi[]; private double ordinati[]; private final int N=10; public Sacchi(){ // costruttore di default sacchi = new double [N]; ordinati = new double [N]; }

Metodi: inizializzazione e stampa public void inizio() { for (int i =0; i<sacchi.length; i++) sacchi[i] = 15.5 - (sacchi.length - i); // per default da 5.5 a 14.5 } public void stampa(double v[]) { for (int i =0; i<v.length; i++) System.out.printf("%4.2f\t", v[i]) ; Stampa con formattazione

Metodo: ricerca del massimo public double max(){ double prov = sacchi[0]; int pos = 0; for (int i =1; i<sacchi.length; i++){ if (sacchi[i] > prov){ prov = sacchi[i]; pos = i; } sacchi[pos] =0; // vuoto il sacco return prov;

Metodo: ordinamento public void ordina() { for (int j = 0; j<ordinati.length; j++) ordinati[j] = max(); }

main public static void main(String[] args) { Sacchi o = new Sacchi(); o.inizio(); System.out.println("\nPrima dell'ordinamento\n"); o.stampa(o.sacchi); // accesso privato risolto dopo chiamata o.ordina(); System.out.println("\n\nDopo l'ordinamento\n"); o.stampa(o.ordinati); System.out.println(""); } } // fine applicazione

OUTPUT Uso stampa con modifica del formato printf (String format, Object... args) System.out.printf("%4.2f\t", v[i]) ; // riserva 4 posizioni // con 2 cifre decimali // formattazione numeri // reali con virgola

… progetto assegnato Si possiedono 9 ceste di vimini piene di nocciole ed una bilancia a due piatti; ciascuna cesta è identificata da un numero decimale. Lo scopo che si vuole raggiungere è ordinarle rispetto al peso in modo che su un foglio compaia un elenco dove il numero che identifica la cesta più pesante sia seguito dai numeri che identificano le ceste di peso via via decrescente.

… progetto assegnato Le attività che si possono eseguire sono: - vuotare cesta - annotare su foglio un numero prendere cesta e metterla su un piatto della bilancia - riporre cesta - scambiare piatto alla cesta   Le domande che possiamo porci: - se una cesta pesa più di un altra - se tutte le ceste sono vuote - se ho finito il confronto tra ceste

Usando unico array: ordinamento “non decrescente” Ogni volta, il massimo si posiziona in fondo all’array … e la dimensione dell’array diminuisce di uno

attributo nella definizione di classe

In alternativa anche array come parametro necessita variabile temporanea

Miglioriamo: progettiamo la classe Sacco chiave: lettera

…. definiamo il tipo Sacco class Sacco { private double peso; private char ch; public Sacco() { // costruttore di default peso = 5.2; // kg ch = 'A'; } public Sacco(double p, char c) { // costruttore parametrico peso = p; ch = c; …. A

// … alcuni metodi di accesso public double getP(){ return peso; } public char getCh(){ return ch; // ridefinizione del metodo toString public String toString() { return (ch + " pesa: " + peso) ; } // fine class Sacco Metodi di oggetti di tipo Sacco Restituisce una rappresentazione testuale dell'oggetto in forma di stringa: è molto utile ad esempio per le stampe.

… progettiamo la classe che usa array di oggetti di tipo Sacco

… definiamo l’applicazione che usa array di oggetti public class OrdinaSacchi { private Sacco sacchi[]; private final int N=10; public OrdinaSacchi(){ sacchi = new Sacco [N]; } Uso oggetti di tipo Sacco public void naiveSort(Sacco v[]){ int p=0, n= v.length; while(n>1) { // mentre sub-array non vuoto p = trovaPosMax(v, n); if (p<n-1) scambia(v, p, n-1); n--; } …

public int trovaPosMax(Sacco v[], int n){ int posMax = 0; for (int i = 1; i<n; i++) if (v[posMax].getP() < v[i].getP()) // peso del Sacco posMax = i; return posMax; } public void scambia(Sacco a[], int ind1, int ind2) { // scambia oggetti Sacco tmp = a[ind1]; a[ind1] = a[ind2]; a[ind2] = tmp; … miglioreremo in seguito, utilizzando Comparable che rappresenta l’interfaccia standard per definire un criterio di ordinamento in Java. Presente nella libreria standard java.util, Comparable<T> consente di ordinare gli oggetti di una classe. In particolare con l’implementazione del metodo compareTo(T o)

public void iniPeggiore(){ for (int i =0; i<sacchi public void iniPeggiore(){ for (int i =0; i<sacchi.length; i++) sacchi[i] = new Sacco (17 - i, (char)('A' + i)); // per default da 17 a 8 } public void ini(){ // già ordinato sacchi[i] = new Sacco (10 + i, (char)('A' + i) ); // per default da 10 a 19 public void stampa(Sacco v[]){ for (int i =0; i<v.length; i++) System.out.print(v[i].toString() + "\n") ; …

main } // fine applicazione public static void main(String[] args) { OrdinaSacchi o = new OrdinaSacchi(); // array di oggetti tipo Sacco o.iniPeggiore(); // poi sostituire con o.ini(); cioè già ordinato System.out.println("\nPrima dell'ordinamento"); o.stampa(o.sacchi); o.naiveSort(o.sacchi); System.out.println("\n\nDopo l'ordinamento"); } } // fine applicazione

Selection sort: ordinamento crescente per minimi successivi con scambio

Migliorabile: metodo scambia public void selectionSort() { for(int i = 0; i < persone.length-1; i++) { int minimo = i; //partiamo dall' i-esimo elemento for(int j = i+1; j < persone.length; j++) { // Qui avviene la selezione, ogni volta // che nell' iterazione troviamo un elemento più piccolo di minimo // facciamo puntare minimo all' elemento trovato if (persone[minimo]>persone[j]) minimo = j; } // Se minimo è diverso dall' elemento di partenza allora // avviene lo scambio if(minimo!=i) { double k = persone[minimo]; // variabile temporanea persone[minimo]= persone[i]; persone[i] = k; } attributo persone private double persone[] = new double[10]; Migliorabile: metodo scambia

... alleniamoci

… passo passo

… anche se inizialmente già ordinato Indipendenza dai dati di ingresso 6 scansioni se l’insieme contiene 7 elementi N-1 scansioni se la dimensione è N … anche se inizialmente già ordinato Complessivo n. di confronti: (N-1) + (N-2) + (N-3) + … + 2 + 1 = N*(N-1)/2  complessità O(N^2/2) Nel caso peggiore: altrettanti scambi necessari

Confronto tra metodo iterativo e ricorsivo

Scambio del valore e della relativa chiave

… array paralleli vs array di oggetti

Scambio public void swapI (int a[], int ind1, int ind2) { // scambia interi int tmp = a[ind1]; a[ind1] = a[ind2]; a[ind2] = tmp; }   public void swapCh (char a[],int ind1, int ind2){ // scambia char char tmp = a[ind1]; public void swap (Object a[], int ind1, int ind2) { // scambia oggetti Object tmp = a[ind1];

nell’ordinamento di un array di oggetti

BUBBLE SORT: ordinamento crescente con scambio tra coppie adiacenti

Idea: si fanno “salire” gli elementi più piccoli (“più leggeri”) verso l’inizio del vettore (“verso l’alto”), scambiandoli con quelli adiacenti.

Dipendenza dai dati di ingresso public void bubbleSort(double[] x) { // semplificato double temp = 0; for(int j=0;j<x.length;j++) { for(int i=j;i<x.length;i++) { if(x[j]>x[i]) { // scambio temp=x[j]; x[j]=x[i]; x[i]=temp; } Dipendenza dai dati di ingresso Nel caso migliore basta una sola scansione, con N-1 confronti → complessità O(N) Nel caso medio, i confronti saranno compresi fra N-1 e N^2/2, a seconda dei dati di ingresso

… ottimizzando Osservazione: se durante una fase non avviene alcuno scambio, allora il vettore è ordinato. Se invece avviene almeno uno scambio, non sappiamo se il vettore è ordinato o meno. ⇒ Possiamo interrompere l’ordinamento appena, durante una fase, non avviene alcuno scambio.

Bubble Sort ottimizzato public void bubbleSortO(int[] a) { // esempio con array di interi int n = a.length; boolean ordinato = false; for (int i=0; i<n-1 && !ordinato; i++) { ordinato = true; for (int j=n-1; j>i; j--) if (a[j-1] > a[j]) { int aux = a[j-1]; // scambio a[j-1] = a[j]; a[j] = aux; ordinato=false; } possibile altra implementazione

 basta una sola scansione dimensione N = 6

Insertion sort

void insertion_sort (int array[ ], int N) { int i, j, carta; for(j = 1; j < N; j++) { carta = array[ j ]; for(i = j -1; (i >= 0) && (array[i] < carta); i--) { array[i+1] = array[i]; // il valore più piccolo sale di una // posizione } array[i+1] = carta; // inserimento della carta // nella opportuna posizione } }

Quick sort: divide et impera Chiamata: quicksort (arr,0,MAX-1);

fosse di lunghezza zero void quicksort (int a[] , int lo, int hi) { // strategia: "dividi ed impera"   // lo è l’indice inferiore, hi è l’indice superiore // dell’area in cui è memorizzato l’array int i=lo, j=hi, h; // variabile per scambio int x = a[(lo+hi)/2]; // scelta valore pivot a metà range   // partizione do { while (a[i]<x) i++; // minori del pivot while (a[j]>x) j--; // maggiori del pivot if (i<=j) { h=a[i]; // scambio a[i]=a[j]; a[j]=h; i++; j--; } } while (i<=j); // ricorsione multipla if (lo<j) quicksort(a, lo, j); if (i<hi) quicksort(a, i, hi); sarebbe pessimo se un sub-array fosse di lunghezza zero

Esempio: corretta scelta pivot dimensione uguale sub-array

Principali algoritmi di ordinamento: • naïve sort (semplice, intuitivo, poco efficiente) • bubble sort (semplice, un poco più efficiente) • insert sort (intuitivo, abbastanza efficiente) • quick sort (non intuitivo, alquanto efficiente se pivot scelto bene) • merge sort (non intuitivo, molto efficiente) è variante del quick sort che produce sempre 2 sub-array di equale ampiezza Per “misurare le prestazioni” di un algoritmo, si conta quante volte viene svolto il confronto fra elementi dell’array. Per approfondire

Riassunto sulla complessità degli algoritmi di ordinamento “O grande” indicazione approssimata di limite superiore L'efficienza di un algoritmo si valuta in base all'utilizzo che l'algoritmo fa delle risorse del calcolatore: CPU Memoria tempo spazio

numero scansioni (parziali/totali) numero confronti, numero scambi array con dimensione N / complessità numero scansioni (parziali/totali) numero confronti, numero scambi