Tutte le implementazioni sono sottoclassi della classe SortAlgorithm che usa la classe SortItem che andremo a commentare. Entrambe queste classi sono state disegnate e implementate da James Gosling, che ha anche implementato Bubble Sort e Quick Sort.
La classe SortItem è essa stessa un applet che si prende cura dell'interfaccia e dell'inizializzazione. Esso crea un oggetto SortAlgorithm, che è anche un thread, si occupa del disegno e fa le pause dopo lo swap. Durante le pause l'applet è ridisegnato.
Usando l'attributo "alg" puoi specificare un algoritmo di sorting. Quando tu clicchi sullo start comincia un thread che anima l'algoritmo di sorting.
import java.awt.*;
public class SortItem extends
java.applet.Applet
implements
Runnable {
Tutte le applet estendono le funzionalità di java.applet.Applet
private
Thread kicker
implements runnable serve per gestire i threads e dare un metodo run
() di default
int
arr[]
Il thread che sta per ordinare (o null)
int oldarr[];
int
h1= -1;
Array che sta per essere ordinato
int oldh1 = h1;
int
h2= -1;
The high water mark
int oldh2 = h2;
String
algName;
The low water mark.
SortAlgorithm
algorithm;
Nome dell'algoritmo
int array_size = 64;
L'algoritmo di sorting (o null)
int rectheight = 3;
int rectspace = 3;
int applet_width = 300;
int applet_height = 475;
protected int pause_milli_secs = 100;
int min_millis = 20;
int max_millis = 1000;
int graphics_y_start;
Button title_button;
Button faster;
Button much_faster;
Button slower;
Button much_slower;
TextField speed;
Panel speed_panel;
void
scramble() {
int
a[] = new int[array_size];
Riempie l'array con numeri random da 0 a n-1
double f = 2.0;
int i;
l'array a[] tratterà oggetti interi e sarà grande array-size=64
for
(i = a.length; --i >= 0;) {
a[i] =
(int)(i * f);
}
for (i = a.length; --i >= 0;) {
per i che va da 63 a 0 con decremento di 1
a[63]=63*2=126, a[62]=62*2=124 etc
int j = (int)(i * Math.random());
int t = a[i];
a[i] = a[j];
a[j] = t;
}
arr = a;
oldarr = new int [array_size];
for (i = 0; i < array_size;
i++) {
oldarr[i] = -1;
}
}
void
pause() {
pause(-1, -1);
}
void
pause(int H1) {
Pause a while. @see SortAlgorithm
pause(H1, -1);
}
void
pause(int H1, int H2) {
Pause a while, and draw the high water mark. @see SortAlgorithm
h1 = H1;
h2 = H2;
if (kicker != null)
{
repaint();
}
try {Thread.sleep(pause_milli_secs);}
catch (InterruptedException e){}
}
Pause a while, and draw the low&high water marks. @see SortAlgorithm
public
void init() {
String at = getParameter("alg");
if (at == null) {
at = "NoSort";
}
new
Button ("Start " + at);
Inizializzazione dell'applet
title_button.
addActionListener
(
creazione oggetto
new
ActionListener()
{
registrazione del componente (oggetto creato con la classe che è
interessata a processare l'evento legato ad un'azione)
public void
actionPerformed
(ActionEvent ae) {
ActionListener è un'interfaccia astratta che intercetta gli
eventi legati alle azioni
startSort();
}
}
);
this.add (title_button);
Quando accade l'evento, il metodo actionPerformed dell'oggetto è invocato
speed_panel = new Panel();
faster = new Button
("F");
faster.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (pause_milli_secs >= min_millis + 20) {
set_pause (pause_milli_secs - 20);
}
}
}
);
much_faster = new Button
("FF");
much_faster.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (pause_milli_secs >= min_millis + 100) {
set_pause (pause_milli_secs - 100);
}
}
}
);
slower = new Button
("S");
slower.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (pause_milli_secs <= max_millis - 20) {
set_pause (pause_milli_secs + 20);
}
}
}
);
much_slower = new Button
("SS");
much_slower.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (pause_milli_secs <= max_millis - 100) {
set_pause (pause_milli_secs + 100);
}
}
}
);
speed = new TextField("Speed", 7);
speed.setEditable(false);
speed_panel.setLayout(new FlowLayout
(FlowLayout.CENTER, 15, 5));
speed_panel.add (much_slower);
speed_panel.add (slower);
speed_panel.add (speed);
speed_panel.add (faster);
speed_panel.add (much_faster);
add (speed_panel);
graphics_y_start = 100;
algName = at + "Algorithm";
scramble();
resize(applet_width, applet_height);
}
termina l'init
protected void set_pause (int millis) {
if ((millis <=
max_millis) && (millis >= min_millis)) {
pause_milli_secs = millis;
speed.setText ("ms " + pause_milli_secs);
}
if (pause_milli_secs
< min_millis + 100) {
much_faster.setEnabled(false);
} else {
much_faster.setEnabled(true);
}
if (pause_milli_secs
< min_millis + 20) {
faster.setEnabled(false);
} else {
faster.setEnabled(true);
}
if (pause_milli_secs
> max_millis - 100) {
much_slower.setEnabled(false);
} else {
much_slower.setEnabled(true);
}
if (pause_milli_secs
> max_millis - 20) {
slower.setEnabled(true);
} else {
slower.setEnabled(false);
}
}
public void
paint(Graphics
g) {
int a[] = arr;
int y;
g.setColor(getBackground());
Paint the array of numbers as a list of horizontal lines of varying
lenghts.
Si cerca di essere veloci cancellando solo le linee che sono
state cambiate dall'ultimo ridisegnamento. Cancella
anche le linee rosse e blu dei watermarks.
y = graphics_y_start;
for
(int i = 0; i < arr.length;i++, y+=
rectheight + rectspace) {y=graphics_y_start=100
vedi sopra, y=y+6
y=9
volte da 100 a 478 cioè 9 volte 63 aggiunte di 6
if (oldarr[i] != arr[i]) {
g.fillRect (0, y, getSize().width, rectheight);
}
if (i == oldh1) {
g.fillRect (0, y, getSize().width, rectheight);
}
if (i == oldh2) {
g.fillRect (0, y, getSize().width, rectheight);
}
}
g.setColor(Color.black);
settiamo il colore nero per disegnare le nuove linee
y = graphics_y_start;
//graphics_y_start=100 vedi sopra
for (int i = 0; i < arr.length; i++, y
+= rectheight + rectspace) {
g.fillRect (0, y,
arr[i] * 2, rectheight);
}
y = graphics_y_start;
if (h1 >= 0) {
g.setColor(Color.red);
y += (h1) * (rectheight
+ rectspace) + (rectheight / 2);
g.drawLine(0, y, getSize().width,
y);
}
y = graphics_y_start;
if (h2 >= 0) {
g.setColor(Color.blue);
y += (h2) * (rectheight
+ rectspace) + (rectheight / 2);
g.drawLine(0, y, getSize().width,
y);
}
oldh1 = h1;
oldh2 = h2;
}
public
void update(Graphics g) {
paint(g);
for (int i = 0; i < arr.length;
i++) {
oldarr[i] = arr[i];
}
}
public
void run() {
Update without erasing the background.
try {
if (algorithm == null) {
algorithm = (SortAlgorithm)Class.forName(algName).newInstance();
algorithm.setParent(this);
}
algorithm.init();
algorithm.sort(arr);
} catch(Exception
e) {
}
}
public
synchronized void stop() {
Run the sorting algorithm. This method is called by class Thread once
the
sorting algorithm is started. @see java.lang.Thread#run @see SortItem#mouseUp
if (algorithm
!= null){
try {
algorithm.stop();
} catch (IllegalThreadStateException e) {
// ignore this exception
}
kicker = null;
}
}
private
synchronized void startSort() {
Stop the applet. Kill any sorting algorithm that is still sorting.
if (kicker == null || !kicker.isAlive()) {
scramble();
repaint();
kicker = new Thread(
this);
kicker.start();
}
}
}
For a Thread to actually do the sorting. This routine makes
sure we do not simultaneously start several sorts if the user
repeatedly clicks on the sort item. It needs to be
synchronoized with the stop() method because they both
manipulate the common kicker variable.