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