Corso di Algoritmi e Strutture Dati
Prima Esercitazione in Laboratorio
26/04/2005
In questa esercitazione consideremo due algoritmi, di cui è riportato il listato Java in calce
al presente documento. L’esercitazione è suddivisa in 2 fasi.
Fase 1
Per ciascun algoritmo si richiede di eseguire una analisi sperimentale dei tempi di
elaborazione, invocando ripetutamente l’algoritmo su input di varia dimensione e
misurando i tempi di elaborazione, riportando i risultati in opportune tabelle,1 ciascuna
composta da numerose righe e due colonne, come nell’esempio schematizzato.
Algoritmo A
input size
tempo (msec o sec)
di esecuzione
10
t1
20
t2
30
t3
40
t4
…
…
Il passo con cui cresce la dimensione dell’input è puramente indicativo e può essere
modificato a seconda delle esigenze.2
Quanto specificato, deve essere eseguito sui due algoritmi insertionSort ed
ennesimoPrimo, dei quali è fornita l’implementazione Java come metodi static.
Il primo metodo ha signature public static void insertionSort(int[] a) e,
dato un array di int, ne esegue l’ordinamento (in senso crescente) attraverso un
algoritmo di ordinamento denominato appunto Insertion Sort.
Il secondo metodo ha signature public static long ennesimoPrimo(long n) e,
dato un long n, calcola e restituisce l’n-esimo numero primo (per convenzione,
ennesimoPrimo(1) restituisce 2). L’algoritmo è piuttosto semplice ed inefficiente.
A tal scopo può essere utile il re-indirizzamento dell’output su file, disponibile al prompt del DOS. Ad
esempio, il comando java Pippo > miofile.txt crea un file di nome miofile.txt contenente tutto
l’output della invocazione java Pippo.
1
2
In alcuni casi, a passi troppo piccoli corrispondono aumenti dei tempi scarsamente percepibili. In questi
casi, conviene utilizzare passi più ampi.
Risorse JFC utili per la sperimentazione (evidenziate in giallo)
java.lang
Class System
java.lang.Object
java.lang.System
public final class System
extends Object
The System class contains several useful class fields and methods. It cannot be instantiated.
Among the facilities provided by the System class are standard input, standard output, and error output streams; access to externally
defined "properties"; a means of loading files and libraries; and a utility method for quickly copying a portion of an array.
Since:
JDK1.0
Field Summary
static PrintStream err
The "standard" error output stream.
static InputStream in
The "standard" input stream.
static PrintStream out
The "standard" output stream.
Method Summary
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
Copies an array from the specified source array, beginning at the specified position, to the
specified position of the destination array.
static long currentTimeMillis()
Returns the current time in milliseconds.
static void exit(int status)
Terminates the currently running Java Virtual Machine.
static void gc()
Runs the garbage collector.
static String getenv(String name)
Deprecated. The preferred way to extract system-dependent information is the system
properties of the java.lang.System.getProperty methods and the corresponding getTypeName
methods of the Boolean, Integer, and Long primitive types. For example:
String classPath = System.getProperty("java.class.path",".");
if (Boolean.getBoolean("myapp.exper.mode"))
enableExpertCommands();
static Properties getProperties()
Determines the current system properties.
static String getProperty(String key)
Gets the system property indicated by the specified key.
static String getProperty(String key, String def)
Gets the system property indicated by the specified key.
static SecurityManager getSecurityManager()
Gets the system security interface.
static int identityHashCode(Object x)
Returns the same hash code for the given object as would be returned by the default
method hashCode(), whether or not the given object's class overrides hashCode().
static void load(String filename)
Loads a code file with the specified filename from the local file system as a dynamic
library.
static void loadLibrary(String libname)
Loads the system library specified by the
libname
argument.
static String mapLibraryName(String libname)
Maps a library name into a platform-specific string representing a native library.
static void runFinalization()
Runs the finalization methods of any objects pending finalization.
static void runFinalizersOnExit(boolean value)
Deprecated. This method is inherently unsafe. It may result in finalizers being called on
live objects while other threads are concurrently manipulating those objects, resulting in erratic
behavior or deadlock.
static void setErr(PrintStream err)
Reassigns the "standard" error output stream.
static void setIn(InputStream in)
Reassigns the "standard" input stream.
static void setOut(PrintStream out)
Reassigns the "standard" output stream.
static void setProperties(Properties props)
Sets the system properties to the
Properties
argument.
static String setProperty(String key, String value)
Sets the system property indicated by the specified key.
static void setSecurityManager(SecurityManager s)
Sets the System security.
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
java.util
Class Random
java.lang.Object
java.util.Random
All Implemented Interfaces:
Serializable
Direct Known Subclasses:
SecureRandom
public class Random
extends Object
implements Serializable
An instance of this class is used to generate a stream of pseudorandom numbers. The class uses a 48-bit seed, which is modified
using a linear congruential formula. (See Donald Knuth, The Art of Computer Programming, Volume 2, Section 3.2.1.)
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate
and return identical sequences of numbers. In order to guarantee this property, particular algorithms are specified for the class
Random. Java implementations must use all the algorithms shown here for the class Random, for the sake of absolute portability of Java
code. However, subclasses of class Random are permitted to use other algorithms, so long as they adhere to the general contracts for
all the methods.
The algorithms implemented by class Random use a protected utility method that on each invocation can supply up to 32
pseudorandomly generated bits.
Many applications will find the random method in class Math simpler to use.
Since:
JDK1.0
See Also:
Math.random(),
Serialized Form
Constructor Summary
Random()
Creates a new random number generator.
Random(long seed)
Creates a new random number generator using a single long seed:
Method Summary
protected
int next(int bits)
Generates the next pseudorandom number.
boolean nextBoolean()
Returns the next pseudorandom, uniformly distributed boolean value from this random number
generator's sequence.
void nextBytes(byte[] bytes)
Generates random bytes and places them into a user-supplied byte array.
double nextDouble()
Returns the next pseudorandom, uniformly distributed double value between 0.0 and 1.0 from this
random number generator's sequence.
float nextFloat()
Returns the next pseudorandom, uniformly distributed float value between 0.0 and 1.0 from this
random number generator's sequence.
double nextGaussian()
Returns the next pseudorandom, Gaussian ("normally") distributed double value with mean 0.0
and standard deviation 1.0 from this random number generator's sequence.
int nextInt()
Returns the next pseudorandom, uniformly distributed int value from this random number
generator's sequence.
int nextInt(int n)
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified
value (exclusive), drawn from this random number generator's sequence.
long nextLong()
Returns the next pseudorandom, uniformly distributed long value from this random number
generator's sequence.
void setSeed(long seed)
Sets the seed of this random number generator using a single
long
seed.
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Fase 2
Consiste nel calcolo analitico degli upper bound degli algoritmi (asintotici, a costi uniformi,
in funzione della dimensione dell’input, worst case). Un volta invidivuata una funzione di
costo f(n) per un algoritmo, effettuare la verifica incrociata con la corrispondente tabella di
costi T(n), calcolata nella Fase 1. In particolare è interessante verificare se il rapporto
f(n)/T(n), al crescere di n, converge verso una costante.
Sebbene sia possibile svolgere tale verifica in molti modi, è consigliabile modificare il
codice Java sviluppato nella Fase 1, per includere anche la stampa dei rapporti f(n)/T(n).
// Classe java di riferimento per l’Esercitazione in laboratorio del 26-4-2005
public class Esercitaz1 {
/*
* ordina l'array a con l'algoritmo di Insertion Sort
*/
public static void insertionSort(int[] a) {
for(int i = 0; i < a.length; i++) {
int tmp = a[i];
int j;
for(j = i; (j > 0) && (tmp < a[j-1]); j--)
a[j] = a[j - 1];
a[j] = tmp;
}
}
/*
* metodo che restituisce, dato un intero n,
* il più grande intero < n che è divisore di n
*
* se tale intero è 1 allora n è numero primo
*/
public static long maxDivisore(long n) {
if(n % 2 == 0) return 2;
long r = (long)Math.sqrt(n);
long d = 3;
while(d <= r) {
if(n % d == 0) return d;
d += 2;
}
return 1;
}
/*
* restituisce l'n-esimo numero primo
*
* ennesimoPrimo(1) restituisce 2, per
* convenzione
*/
public static long ennesimoPrimo(long n) {
if(n == 1) return 2; // convenzione
if(n == 2) return 3;
long i = 3;
long contaPrimi = 2;
while(contaPrimi < n) {
i += 2;
if(maxDivisore(i) == 1) contaPrimi++;
}
return i;
}
}