Vector e Enumeration (III parte) •Ordinamento • Array 2 Ordinamento di Vector: selection sort Risultato: un Vector v ordinato in senso crescente – se j < k allora v.elementAt(j) <= v.elementAT(k) Procedimento informale – Inserire nella posizione 0 l’elemento giusto (il più piccolo tra quelli compresi tra le posizioni 0 e n-1, dove n == v.size()) – Inserire l’elemento giusto in posizione 1 (il più piccolo tra quelli compresi tra le posizioni 1 e n-1) – Inserire l’elemento giusto in posizione 2 (il più piccolo tra quelli compresi tra le posizioni 2 e n-1) – Continuare fino a quando la posizione n-2 non contiene l’elemento giusto. A questo punto anche la posizione n-1 conterrà l’elemento giusto (il più grande) 1 3 Ordinamento di Vector: variabili E’ necessario tenere conto della posizione k raggiunta. – La posizione k divide il Vector in due zone … Per comodità la variabile n indica la dimensione del Vector int k; int n=v.size(); // k== the index of the next position in the Vector // to take care of. // All elements to the left of k are less than or // equal to the elements at k or to the right of k. // All elements to the left of k are in ascending // order. // n== number of elements in the Vector. 4 Ordinamento di Vector: Scheletro del codice static void sort(Vector v) { // al termine dell’esecuzione gli elementi di v // saranno ordinati in senso crescente int k; // k è la posizione all’interno del vettore da considerare al passo // successivo // Tutti gli elementi a sinistra di k sono minori o uguali // degli elementi a destra // Tutti gli elementi a sinistra di k sono ordinati int n=v.size(); // n: numero di elementi del Vector … while (condition) { body … } 2 5 Ordinamento di Vector: Condizione del while Il procedimento termina quando si raggiunge l’ultima posizione (n-1). while (k != n-1) body // k == n-1, per cui gli elementi 0 .. n-2 sono già ordinati // poiché questi elementi vengono prima di quello in posizione n-1, // anche quest’ultimo risulta ordinato . 6 Ordinamento: Inizializzazione e garanzia di terminazione Inizializzazione – La definizione di k indica che è l’indice della prossima posizione di cui ci si deve occupare. Secondo il procedimento informale all’inizio deve essere 0 k = 0; Garanzia di terminazione – Incrementando k di 1 nel corpo del ciclo sappiamo che k finirà per valere n-1 k++; 3 7 Ordinamento di Vector: Completamento del ciclo Prima di incrementare k bisogna assicurarsi che la posizione k riceva l’elemento più piccolo compreso tra le posizioni k e n-1 int j = getSmallest(k, v); // variante del metodo getSmallest A questo punto si può usare il metodo Exchange per scambiare gli elementi di posizioni k e j exchange(v, k, j); 8 Metodo di Ordinamento di Vector static void sort(Vector v) {// al termine dell’esecuzione gli elementi di v // saranno ordinati in senso crescente int k; // k è la posizione all’interno del vettore da considerare al passo // successivo // Tutti gli elementi a sinistra di k sono minori o uguali // degli elementi a destra // Tutti gli elementi a sinistra di k sono ordinati int n=v.size(); // n: numero di elementi del Vector k = 0; while (k != n-1) { int j = getSmallest(k, v); exchange(v, k, j); k++; } } 4 9 Metodo getSmallest modificato static int getSmallest(Vector v, int k) { if (v==null || v.size()==k) return -1; int i; int small = k; i = k+1; while (i != v.size()) { String current = (String) v.elementAt(i); String smallest = (String) v.elementAt(small); if (current.compareTo(smallest)<0) small = i; i++; } return small; } 10 Metodo exchange static void exchange(Vector v, int k, int j) { Object obk = v.elementAt(k); v.setElementAt(v.elementAt(j),k); v.setElementAt(obk,j); } 5 11 Altri algoritmi di Ordinamento: Insertion Sort Visita totale: ad ogni passo gli elementi che precedono l’elemento corrente sono ordinati si inserisce l’elemento corrente nella posizione che garantisce il mantenimento dell’ordinamento gli elementi precedenti maggiori sono spostati in avanti … il primo elemento è già ordinato … 12 Insertion Sort parte non ordinata parte ordinata 10 20 30 18 18 6 18 20 15 12 7 24 elemento corrente parte non ordinata parte ordinata 10 4 30 6 4 15 12 7 24 6 13 Algoritmo di Insertion Sort for(i = 1; i < n; i++) memorizza l’elemento di posizione i in una variabile temporanea next sia j la posizione in cui deve essere inserito next: sposta in avanti gli elementi di posizioni tra i-1 e j, inserisci next in posizione j 14 Altri algoritmi di Ordinamento: Bubble Sort Algoritmo iterativo: – finché il Vector non risulta ordinato si effettua una visita durante la quale si scambiano gli elementi adiacenti che non risultano ordinati – se è stato effettuato almeno uno scambio allora il Vector non è ordinato – nota che ad ogni passo l’elemento più grande viene portato nella sua posizione finale, per cui dopo il passo i-esimo, gli elementi tra le posizioni n-i ed n-1 risultano ordinati e nelle loro posizioni finali – l’algoritmo converge in al più n-1 passi (dove n è il numero di elementi del Vector) 7 15 Bubble Sort 1a iterazione 2a iterazione 10 20 7 18 6 4 10 7 18 6 4 20 10 7 20 18 6 4 7 10 18 6 4 20 10 7 18 20 6 4 7 10 6 18 4 20 10 7 18 6 20 4 7 10 6 4 18 20 10 7 18 6 4 20 ...... 16 Algoritmo di Bubble sort boolean ordinato = false; i = 1; while (i < n && ! ordinato) ordinato = true; scambia gli elementi adiacenti che non risultano ordinati tra le posizioni 0 e n-i e poni ordinato a false se viene effettuato almeno uno scambio i = i +1; 8 17 Altri algoritmi di Ordinamento: Distribuzione e fusione Algoritmo iterativo: – finché il Vector non risulta ordinato si distribuiscono gli elementi in due Vector d’appoggio – si cambia Vector d’appoggio ogni volta che viene interrotta una sequenza ordinata – se uno dei due Vector risulta vuoto, allora la sequenza degli elementi nel Vector originario era ordinata, altrimenti si fondono i due Vector per ottenere un nuovo Vector (più ordinato del precedente) – ad ogni passo il numero di interruzioni nelle sequenze ordinate diminuisce – l’algoritmo converge in al più n-1 passi (dove n è il numero di elementi del Vector) 18 10 10 20 10 7 18 10 6 7 10 18 6 4 6 7 10 18 10 18 7 10 6 20 6 6 6 4 20 18 Esempio 4 4 4 4 18 7 4 4 7 6 7 7 20 20 20 18 20 18 20 9 19 Algoritmo di Distribuzione e Fusione boolean ordinato = false; i = 1; while (i < n && ! ordinato) distribuisci gli n elementi del Vector v sui Vector x e y (partendo da x); se il Vector y è vuoto ordinato = TRUE; altrimenti fondi I Vector x e y nel Vector v i = i +1; 20 Introduzione agli array Una struttura del linguaggio che usa l’indicizzazione per supportare la collezione di dati Caratteristiche comuni tra array e Vector: – – – – – – Consistono di una o più posizioni Ogni posizione è indicizzata da un numero intero l’indice della prima posizione è 0 Sono degli oggetti Devono essere creati con l’operatore new Ci si riferisce ad essi con una variabile di riferimento 10 21 Differenze tra array e Vector L’array non è una classe, fa parte del linguaggio L’array non ha metodi, per accedere agli elementi si usano simboli del linguaggio L’array ha un campo, chiamato length, che indica il numero di elementi contenuti nell’array – Vector usa il metodo size Gli elementi dell’array possono contenere dati primitivi, come ad esempio valori interi e riferimenti ad oggetti Il tipo degli elementi di un array deve essere specificato nella dichiarazione dell’array Gli array non possono estendersi (cardinalità fissata) 22 Dichiarazione di array int [] lottoNumbers; // Variabile di riferimento ad un array // i cui elementi sono tutti interi String [] winners; // Variabile di riferimento ad un array // i cui elementi sono riferimenti a String Employee [] personnel; // Variabile di riferimento ad un array // i cui elementi sono riferimenti a oggetti Employee Queste dichiarazioni non sono una novità – Il parametro del metodo main è String [] Queste dichiarazioni non creano array 11 23 Creazione di array Per creare un array si usa l’operatore new lottoNumbers = new int [6]; // Crea un array di 6 interi e // e assegna il riferimento a lottoNumbers Pertanto, il valore di lottoNumbers.length è 6 – Dopo length non ci sono parentesi perché non si tratta di un metodo, ma di un campo (variabile) 24 Accesso agli elementi di un array Per assegnare un valore ad un elemento di un array a[k] = valore; // Assegna valore all’elemento di posizione k – Il valore assegnato deve essere dello stesso tipo degli elementi dell’array – E’ l’analogo di setElementAt per i Vector Per usare il valore di un elemento di un array int x = 3 * a[k]; int y = a[k]; – E’ l’analogo di elementAt per i Vector Gli elementi di un array somigliano a variabili – gli array sono detti a volte variabili indicizzate 12 25 import java.lang.*; import java.io.*; class ReverseIntegers { public static void main(String[] a) throws Exception { BufferedReader kb = new BufferedReader(new InputStreamReader(System.in)); int[] z = new int[100]; int i=0; // Next position to fill; all positions before position i have been filled. while (i!=100) { z[i] = Integer.parseInt(kb.readLine()); i++; } int k=99; // k== the index of the next position in array to print. while (k!=-1) { System.out.println(z[k]); --k; } } } Esempio 26 Vector o array ? Rispetto ai Vector l’array offre i seguenti vantaggi – Possibilità di memorizzare dati primitivi – Si può accedere agli elementi senza inviare messaggi (maggiore efficienza) • Tuttavia questa efficienza è niente rispetto a quella esistente tra ricerca binaria e ricerca sequenziale (la ricerca binaria in un Vector più veloce della ricerca sequenziale in un array) – Essendo tipizzati,gli array offrono una specie di verifica, durante la compilazione, che i Vector non prevedono. Svantaggi di array rispetto a Vector – La dimensione degli array è fissata e non può essere cambiata – Gli array non offrono la ricca serie di operazioni offerte da un Vector come ad esempio insertElementAt 13 27 Dal Vector all’array La maggior parte del codice scritto per i Vector può essere convertito in codice che usa gli array – La sostituzione dei metodi size, elementAt e setElementAt è immediata – La sostituzione dei metodi insertElementAt e removeElementAt potrebbe richiedere l’introduzione di cicli che usano setElementAt Esempio: codice per la ricerca di una String s in un Vector v int k = 0; while ( k != v.size() && ! s.equals(v.elementAt(k)) k++; if (k==v.size()) System.out.println(r+” Not Found!”); else System.out.println(r+” Found at “ +“position “ + k); 28 Codice per la ricerca di una String in un array Esempio: codice per la ricerca di una String s in un array v int k = 0; while ( k != v.length && ! s.equals(v[k]) k++; if (k == v.length) System.out.println(r+” Not Found!”); else System.out.println(r+” Found at “ +“position “ + k); 14 29 Argomenti sulla linea di comando Abbiamo sempre dichiarato, come parametro del metodo static main,un array di riferimenti a String public static void main(String[] arg) Il parametro arg è un array di String che corrispondono agli argomenti della linea di comando dell’applicazione – Sono i valori String che sono forniti quando è invocato il programma – Per esempio, nell’invocazione java program grant sherman sheridan gli argomenti della line di comando sono grant, sherman e sheridan, per cui i valori nell’array arg diventano: arg[0] è “grant”, arg[1] è “sherman”, arg[2] è “sheridan” import java.io.*; class CopyFile { public static void main(String[] a) throws IOException { BufferedReader in = new BufferedReader( new InputStreamReader( new FileInputStream( new File(a[0])))); PrintStream out = new PrintStream( new FileOutputStream( new File(a[1]))); String s = in.readLine(); while (s!=null) { out.println(s); s = in.readLine(); } } } 30 Esempio: copia di file 15 31 String e indici Una String è una sequenza di caratteri la cui posizione nella sequenza può essere individuata da un numero intero Anche le String sono indicizzate a partire da 0 La classe String offre un metodo charAt che (come elementAt della classe Vector) restituisce il carattere posizionato in un determinato indice dell’oggetto String char c = “abcdefg”.charAt(3); Assegna il valore char ‘d’ alla variabile char d Il tipo primitivo char permette di rappresentare più di 64000 caratteri diversi – numeri, segni di punteggiatura e alfabeti di tutto il mondo 32 Esempio Determinare se String s1 è il prefisso di String s2 int k; // Position k is the next one to check; // the Strings match in all positions before k. k = 0; while (k != s1.length() && k != s2.length() && s1.charAt(k) == s2.charAt(k)) k++; boolean s1IsAPrefix = k == s1.length(); 16 33 Cenni su array bidimensionali Dichiarazione – int [][] matrice; Creazione – matrice = new int[10][20]; Accesso – matrice[i][j] = 3 + x; – y = matrice[i][j] + 4; Per avere il numero di righe (10 nel nostro caso): – matrice.length Per avere il numero di colonne (20 nel nostro caso): – matrice[i].length – D’altra parte matrice[i] è un array (i-esima riga) 17