414 lines
14 KiB
Java
414 lines
14 KiB
Java
import java.awt.Color;
|
|
import java.awt.Font;
|
|
|
|
import algoanim.animalscript.AnimalScript;
|
|
import algoanim.exceptions.LineNotExistsException;
|
|
import algoanim.primitives.ArrayMarker;
|
|
import algoanim.primitives.IntArray;
|
|
import algoanim.primitives.SourceCode;
|
|
import algoanim.primitives.generators.Language;
|
|
import algoanim.properties.AnimationPropertiesKeys;
|
|
import algoanim.properties.ArrayMarkerProperties;
|
|
import algoanim.properties.ArrayProperties;
|
|
import algoanim.properties.SourceCodeProperties;
|
|
import algoanim.util.Coordinates;
|
|
|
|
/**
|
|
* @author Dr. Guido Rößling <roessling@acm.org>
|
|
* @version 1.0 2007-05-30
|
|
*
|
|
*/
|
|
public class APIExample {
|
|
|
|
/**
|
|
* The concrete language object used for creating output
|
|
*/
|
|
private Language lang;
|
|
|
|
/**
|
|
* Default constructor
|
|
* @param l the conrete language object used for creating output
|
|
*/
|
|
public APIExample(Language l) {
|
|
// Store the language object
|
|
lang = l;
|
|
// This initializes the step mode. Each pair of subsequent steps has to
|
|
// be divdided by a call of lang.nextStep();
|
|
lang.setStepMode(true);
|
|
}
|
|
|
|
private static final String DESCRIPTION =
|
|
"QuickSort wählt ein Element aus der zu sortierenden Liste aus "
|
|
+"(Pivotelement) und zerlegt die Liste in zwei Teillisten, eine untere, "
|
|
+"die alle Elemente kleiner und eine obere, die alle Elemente gleich oder "
|
|
+"größer dem Pivotelement enthält.\nDazu wird zunächst ein Element von unten "
|
|
+"gesucht, das größer als (oder gleichgroß wie) das Pivotelement und damit "
|
|
+"für die untere Liste zu groß ist. Entsprechend wird von oben ein kleineres "
|
|
+"Element als das Pivotelement gesucht. Die beiden Elemente werden dann "
|
|
+"vertauscht und landen damit in der jeweils richtigen Liste.\nDer Vorgang "
|
|
+"wird fortgesetzt, bis sich die untere und obere Suche treffen. Damit sind "
|
|
+"die oben erwähnten Teillisten in einem einzigen Durchlauf entstanden. "
|
|
+"Suche und Vertauschung können in-place durchgeführt werden."
|
|
+"\n\nDie noch unsortierten Teillisten werden über denselben Algorithmus "
|
|
+"in noch kleinere Teillisten zerlegt (z. B. mittels Rekursion) und, sobald "
|
|
+"nur noch Listen mit je einem Element vorhanden sind, wieder zusammengesetzt. "
|
|
+"Die Sortierung ist damit abgeschlossen.";
|
|
|
|
private static final String SOURCE_CODE = "public void quickSort(int[] array, int l, int r)" // 0
|
|
+ "\n{" // 1
|
|
+ "\n int i, j, pivot;" // 2
|
|
+ "\n if (r>l)" // 3
|
|
+ "\n {" // 4
|
|
+ "\n pivot = array[r];" // 5
|
|
+ "\n for (i = l; j = r - 1; i < j; )" // 6
|
|
+ "\n {" // 7
|
|
+ "\n while (array[i] <= pivot && j > i)" // 8
|
|
+ "\n i++;" // 9
|
|
+ "\n while (pivot < array[j] && j > i)" // 10
|
|
+ "\n j--;" // 11
|
|
+ "\n if (i < j)" // 12
|
|
+ "\n swap(array, i, j);" // 13
|
|
+ "\n }" // 14
|
|
+ "\n if (pivot < array[i])" // 15
|
|
+ "\n swap(array, i, r);" // 16
|
|
+ "\n else" // 17
|
|
+ "\n i=r;" // 18
|
|
+ "\n quickSort(array, l, i - 1);" // 19
|
|
+ "\n quickSort(array, i + 1, r);" // 20
|
|
+ "\n }" // 21
|
|
+ "\n}"; // 22
|
|
|
|
/**
|
|
* Sort the int array passed in
|
|
* @param a the array to be sorted
|
|
*/
|
|
public void sort(int[] a) {
|
|
// Create Array: coordinates, data, name, display options,
|
|
// default properties
|
|
|
|
// first, set the visual properties (somewhat similar to CSS)
|
|
ArrayProperties arrayProps = new ArrayProperties();
|
|
arrayProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.BLACK);
|
|
arrayProps.set(AnimationPropertiesKeys.FILL_PROPERTY, Color.WHITE);
|
|
arrayProps.set(AnimationPropertiesKeys.FILLED_PROPERTY, Boolean.TRUE);
|
|
arrayProps.set(AnimationPropertiesKeys.ELEMENTCOLOR_PROPERTY,
|
|
Color.BLACK);
|
|
arrayProps.set(AnimationPropertiesKeys.ELEMHIGHLIGHT_PROPERTY,
|
|
Color.RED);
|
|
arrayProps.set(AnimationPropertiesKeys.CELLHIGHLIGHT_PROPERTY,
|
|
Color.YELLOW);
|
|
|
|
// now, create the IntArray object, linked to the properties
|
|
IntArray ia = lang.newIntArray(new Coordinates(20, 100), a, "intArray",
|
|
null, arrayProps);
|
|
|
|
// start a new step after the array was created
|
|
lang.nextStep();
|
|
|
|
// Create SourceCode: coordinates, name, display options,
|
|
// default properties
|
|
|
|
// first, set the visual properties for the source code
|
|
SourceCodeProperties scProps = new SourceCodeProperties();
|
|
scProps.set(AnimationPropertiesKeys.CONTEXTCOLOR_PROPERTY, Color.BLUE);
|
|
scProps.set(AnimationPropertiesKeys.FONT_PROPERTY, new Font("Monospaced",
|
|
Font.PLAIN, 12));
|
|
|
|
scProps.set(AnimationPropertiesKeys.HIGHLIGHTCOLOR_PROPERTY,
|
|
Color.RED);
|
|
scProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.BLACK);
|
|
|
|
// now, create the source code entity
|
|
SourceCode sc = lang.newSourceCode(new Coordinates(40, 140), "sourceCode",
|
|
null, scProps);
|
|
|
|
// Add the lines to the SourceCode object.
|
|
// Line, name, indentation, display dealy
|
|
sc.addCodeLine("public void quickSort(int[] array, int l, int r)", null, 0, null); // 0
|
|
sc.addCodeLine("{", null, 0, null);
|
|
sc.addCodeLine("int i, j, pivot;", null, 1, null);
|
|
sc.addCodeLine("if (r>l)", null, 1, null); // 3
|
|
sc.addCodeLine("{", null, 1, null); // 4
|
|
sc.addCodeLine("pivot = array[r];", null, 2, null); // 5
|
|
sc.addCodeLine("for (i = l; j = r - 1; i < j; )", null, 2, null); // 6
|
|
sc.addCodeLine("{", null, 2, null); // 7
|
|
sc.addCodeLine("while (array[i] <= pivot && j > i)", null, 3, null); // 8
|
|
sc.addCodeLine("i++;", null, 4, null); // 9
|
|
sc.addCodeLine("while (pivot < array[j] && j > i)", null, 3, null); // 10
|
|
sc.addCodeLine("j--;", null, 4, null); // 11
|
|
sc.addCodeLine("if (i < j)", null, 3, null); // 12
|
|
sc.addCodeLine("swap(array, i, j);", null, 4, null); // 13
|
|
sc.addCodeLine("}", null, 2, null); // 14
|
|
sc.addCodeLine("if (pivot < array[i])", null, 2, null); // 15
|
|
sc.addCodeLine("swap(array, i, r);", null, 3, null); // 16
|
|
sc.addCodeLine("else", null, 2, null); // 17
|
|
sc.addCodeLine("i=r;", null, 3, null); // 18
|
|
sc.addCodeLine(" quickSort(array, l, i - 1);", null, 2, null); // 19
|
|
sc.addCodeLine(" quickSort(array, i + 1, r);", null, 2, null); // 20
|
|
sc.addCodeLine(" }", null, 1, null); // 21
|
|
sc.addCodeLine("}", null, 0, null); // 22
|
|
|
|
lang.nextStep();
|
|
// Highlight all cells
|
|
ia.highlightCell(0, ia.getLength() - 1, null, null);
|
|
try {
|
|
// Start quicksort
|
|
quickSort(ia, sc, 0, (ia.getLength() - 1));
|
|
} catch (LineNotExistsException e) {
|
|
e.printStackTrace();
|
|
}
|
|
sc.hide();
|
|
ia.hide();
|
|
lang.nextStep();
|
|
}
|
|
|
|
/**
|
|
* counter for the number of pointers
|
|
*
|
|
*/
|
|
private int pointerCounter = 0;
|
|
|
|
/**
|
|
* Quicksort: Sort elements using a pivot element between [l, r]
|
|
*
|
|
* @param array the IntArray to be sorted
|
|
* @param codeSupport the underlying code instance
|
|
* @param l the lower border of the subarray to be sorted
|
|
* @param l the upper border of the subarray to be sorted
|
|
*/
|
|
private void quickSort(IntArray array, SourceCode codeSupport, int l, int r)
|
|
throws LineNotExistsException {
|
|
// Highlight first line
|
|
// Line, Column, use context colour?, display options, duration
|
|
codeSupport.highlight(0, 0, false);
|
|
lang.nextStep();
|
|
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(0, 0, false, 2, 0);
|
|
|
|
// Create two markers to point on i and j
|
|
pointerCounter++;
|
|
// Array, current index, name, display options, properties
|
|
ArrayMarkerProperties arrayIMProps = new ArrayMarkerProperties();
|
|
arrayIMProps.set(AnimationPropertiesKeys.LABEL_PROPERTY, "i");
|
|
arrayIMProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.BLACK);
|
|
ArrayMarker iMarker = lang.newArrayMarker(array, 0, "i" + pointerCounter,
|
|
null, arrayIMProps);
|
|
pointerCounter++;
|
|
|
|
ArrayMarkerProperties arrayJMProps = new ArrayMarkerProperties();
|
|
arrayJMProps.set(AnimationPropertiesKeys.LABEL_PROPERTY, "j");
|
|
arrayJMProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.BLACK);
|
|
ArrayMarker jMarker = lang.newArrayMarker(array, 0, "j" + pointerCounter,
|
|
null, arrayJMProps);
|
|
|
|
int i, j;
|
|
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(2, 0, false, 3, 0);
|
|
// this statement is equivalent to
|
|
// codeSupport.unhighlight(2, 0, false);
|
|
// codeSupport.highlight(3, 0, false);
|
|
|
|
// Create a marker for the pivot element
|
|
int pivot;
|
|
pointerCounter++;
|
|
ArrayMarkerProperties arrayPMProps = new ArrayMarkerProperties();
|
|
arrayPMProps.set(AnimationPropertiesKeys.LABEL_PROPERTY, "pivot");
|
|
arrayPMProps.set(AnimationPropertiesKeys.COLOR_PROPERTY, Color.BLUE);
|
|
|
|
ArrayMarker pivotMarker = lang.newArrayMarker(array, 0,
|
|
"pivot" + pointerCounter, null, arrayPMProps);
|
|
|
|
lang.nextStep();
|
|
codeSupport.unhighlight(3, 0, false);
|
|
if (r > l) {
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.highlight(5, 0, false);
|
|
|
|
// Receive the value of the pivot element
|
|
pivot = array.getData()[r];
|
|
// Move marker to that position
|
|
pivotMarker.move(r, null, null);
|
|
|
|
|
|
lang.nextStep();
|
|
codeSupport.unhighlight(5, 0, false);
|
|
for (i = l, j = r - 1; i < j;) {
|
|
// Highlight next line
|
|
codeSupport.highlight(6, 0, false);
|
|
// Move the two markers i,j to their proper positions
|
|
iMarker.move(i, null, null);
|
|
jMarker.move(j, null, null);
|
|
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(6, 0, false, 8, 0);
|
|
|
|
while (array.getData()[i] <= pivot && j > i) {
|
|
lang.nextStep();
|
|
i++;
|
|
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(8, 0, false, 9, 0);
|
|
// Move marker i to its next position
|
|
iMarker.move(i, null, null);
|
|
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(9, 0, false, 8, 0);
|
|
}
|
|
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(8, 0, false, 10, 0);
|
|
while (pivot < array.getData()[j] && j > i) {
|
|
lang.nextStep();
|
|
|
|
j--;
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(10, 0, false, 11, 0);
|
|
|
|
// Move marker j to its next position
|
|
jMarker.move(j, null, null);
|
|
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(11, 0, false, 10, 0);
|
|
|
|
}
|
|
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(10, 0, false, 12, 0);
|
|
|
|
|
|
if (i < j) {
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(12, 0, false, 13, 0);
|
|
|
|
|
|
// Swap the array elements at position i and j
|
|
array.swap(i, j, null, null);
|
|
}
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(13, 0, false, 12, 0);
|
|
|
|
} // end for...
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(6, 0, false, 13, 0);
|
|
|
|
|
|
lang.nextStep();
|
|
if (pivot < array.getData()[i]) {
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(15, 0, false, 16, 0);
|
|
|
|
// Swap the array elements at position i and r
|
|
array.swap(i, r, null, null);
|
|
// Set pivot marker to position i
|
|
pivotMarker.move(i, null, null);
|
|
|
|
lang.nextStep();
|
|
codeSupport.unhighlight(16, 0, false);
|
|
} else {
|
|
i = r;
|
|
// Highlight next line
|
|
codeSupport.toggleHighlight(15, 0, false, 18, 0);
|
|
// Move marker i to position r
|
|
iMarker.move(r, null, null);
|
|
|
|
lang.nextStep();
|
|
codeSupport.unhighlight(18, 0, false);
|
|
}
|
|
// Highlight the i'th array element
|
|
array.highlightElem(i, null, null);
|
|
|
|
lang.nextStep();
|
|
codeSupport.highlight(19, 0, false);
|
|
|
|
lang.nextStep();
|
|
codeSupport.unhighlight(19, 0, false);
|
|
|
|
// Unhighlight cells from i to r
|
|
// this part is not scheduled...
|
|
array.unhighlightCell(i, r, null, null);
|
|
// Apply quicksort to the left array part
|
|
iMarker.hide();
|
|
jMarker.hide();
|
|
pivotMarker.hide();
|
|
quickSort(array, codeSupport, l, i - 1);
|
|
iMarker.show();
|
|
jMarker.show();
|
|
pivotMarker.show();
|
|
|
|
// Left recursion finished.
|
|
lang.nextStep();
|
|
// Highlight cells l to r
|
|
array.highlightCell(l, r, null, null);
|
|
codeSupport.highlight(20, 0, false);
|
|
|
|
lang.nextStep();
|
|
codeSupport.unhighlight(20, 0, false);
|
|
// Unhighlight cells l to i
|
|
array.unhighlightCell(l, i, null, null);
|
|
// Apply quicksort to the right array part
|
|
iMarker.hide();
|
|
jMarker.hide();
|
|
pivotMarker.hide();
|
|
quickSort(array, codeSupport, i + 1, r);
|
|
iMarker.show();
|
|
jMarker.show();
|
|
pivotMarker.show();
|
|
}
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.highlight(21, 0, false);
|
|
lang.nextStep();
|
|
// Highlight next line
|
|
codeSupport.highlight(22, 0, false);
|
|
|
|
lang.nextStep();
|
|
// Unhighlight cells from l to r
|
|
array.unhighlightCell(l, r, null, null);
|
|
lang.nextStep();
|
|
iMarker.hide();
|
|
jMarker.hide();
|
|
pivotMarker.hide();
|
|
}
|
|
|
|
protected String getAlgorithmDescription() {
|
|
return DESCRIPTION;
|
|
}
|
|
|
|
protected String getAlgorithmCode() {
|
|
return SOURCE_CODE;
|
|
}
|
|
|
|
public String getName() {
|
|
return "Quicksort (pivot=last)";
|
|
}
|
|
|
|
public String getDescription() {
|
|
return DESCRIPTION;
|
|
}
|
|
|
|
public String getCodeExample() {
|
|
return SOURCE_CODE;
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
// Create a new animation
|
|
// name, author, screen width, screen height
|
|
Language l = new AnimalScript("Quicksort Animation", "Dr. Guido Rößling", 640, 480);
|
|
APIExample s = new APIExample(l);
|
|
int[] a = {7,3,2,4,1,13,52,13,5,1};
|
|
s.sort(a);
|
|
System.out.println(l);
|
|
}
|
|
}
|