Einführung/Algorithmen und Datenstrukturen Belegaufgabe Sommersemester 2005 Sortieren mittels Deap Das Programm liegt als Download in Form einer JAR-Datei unter folgenden Adressen bereit: http://www.tstrutz.de http://www.cs.uni-magdeburg.de/~burgmann/ Bearbeiter: Tobias Strutz Nils Burgmann [email protected] [email protected] Sortieren mittels Deap Diese JAVA-Applikation stellt das sortiern mit Hilfe eines Deaps dar. Ein Deap ist ein Doppel-Heap. Er besteht aus 2 Heaps, einem Min-Heap und einem Max-Heap, die eine gemeinsame Wurzel haben. Diese wird nicht mit einem Wert belegt. In der folgenden Abbildung ist so ein Deap dargestellt: Abbildung 1: Beispiel für einen Deap. Da in beiden Teilbäumen unter der Wurzel jeweils die Heap-Eigenschaften beim einfügen eines neuen Elements kontrolliert und gegebenen Falls wieder hergestellt werden, beinhalten die Kindknoten der Wurzel stets das größte und das kleinste Element des Deaps. So kann zum Sortieren einer Folge diese nach der Übergabe in den Deap gleichzeitig von hinten und von vorn wieder aufgebaut werden. Um die Applikation kompakt zu halten heben wir sie in einer JAR-Datei hinterlegt. Um das Programm so ausführen zu können gibt man in der Eingabeaufforderung in dem Verzeichnis, in dem sich diese JAR-Datei befindet folgende Zeile ein: java –jar deap.jar DeapFrame.class deap.jar ist dabei die das JAVA-Archive, welches alle benötigten Klassen enthält. DeapFrame.class ist die Klasse, die das Programm ausführt. Seite 2 von 4 Belegaufgaben Sommersemester 2005 Abbildung 2: Die Programmoberfläche. Die Programmoberfläche ist sehr einfach gehalten. Dominiert wird sie durch das Anzeigefeld für den Baum, der als logische Datenstruktur dem Deap zu Grunde liegt. Darunter, der gelbe Streifen ist das Ausgabefeld für zum Beispiel die sortierte Sequenz. Im untersten Bereich befinden sich die eigentlichen Bedienelemente. Ganz links ist das Eingabefeld für neue Werte. Hier bestätigt man mit der Enter-Taste den eingegebenen Wert und automatisch wird dieser als neues Element an die richtige stelle im Deap eingeordnet. Der Button „Init“ erleichtert einem diese Arbeit. Er füllt den Baum sofort mit einer hinterlegten Zahlenfolge auf. Mit dem Button „Size“ erhält man die aktuelle Anzahl von Elementen, die sich im Deap befinden. „Remove Min“ entfernt des kleinste Element, „remove Max“ dementsprechend das größte. Mit dem Button „Sort“ wird eine sortierte Sequenz aus den Elementen im Deap erzeugt. Die Ausgabe dazu erfolgt wie oben bereits erwähnt, im gelben Bereich des Programmfensters. Der letzte Button ist mit „Reset“ bezeichnet. Er setzt den Deap zurück auf Null. Die Klasse Deap ist die eigentliche Basis dieser Applikation. Als logische Struktur liegt ihr ein binärer Baum zu Grunde. In dessen Wurzel wird kein Wert gespeichert. Die Kinder der Wurzel beinhalten immer das kleinste und das größte Element. Das heißt, sie sind im eigentlichen Sinn Wurzeln für einen Min-Heap und einen Max-Heap. Die Knoten im MaxHeap sind immer größer als die Knoten an gleicher Stelle im Min-Heap. Im Max-Heap ist ein Elternknoten immer größer als seine Kinder. Im Min-Heap ist es genau umgekehrt. Die Ebenen dieses Baums sind vollständig. Die letzte Ebene wird von links nach rechts aufgefüllt. Mit diesen Eigenschaften lässt sich die Klasse in groben Zügen wie folgt implementieren: Mit der Methode insert wird das Einfügen eines neuen Elements realisiert. Als erstes wird es einfach an das Ende, also an die letzte Position des Deaps, angehängt. Dann werden alle Eigenschaften überprüft und der neue Knoten wird so lange mit den schon vorhandenen Knoten getauscht, bis keine Verletzung mehr vorliegt. Dies geschieht im Wesentlichen mit den Methoden maxInsert und minInsert. Sie lassen den Knoten im jeweiligen Heap so lang „aufsteigen“, bis er an seiner korrekten Position angelangt ist. Seite 3 von 4 Sortieren mittels Deap Um Elemente aus dem Deap zu entnehmen gibt es zwei Methoden: removeMin und removeMax. Wird das kleinste oder größte Element entnommen muss das neue kleinste oder eben größte Element gesucht werden. Dazu wird der letzte Knoten an die Stelle des entnommenen Elements geschrieben. Jetzt „sinkt“ dieser Knoten im jeweiligen Teilbaum so lang, bis alle Deap-Eigenschaften wieder erfüllt sind. Dazu muss auch stets überprüft werden, ob der passende Partnerknoten im anderen Teilbaum auch wirklich kleiner, beim Max-Heap, oder größer, im Min-Heap, ist. Das „Sinken“ übernehmen die Methoden sinkInMin und SinkInMax. Wie eingangs erwähnt ist das logische Konstrukt für diese Datenstruktur ein binärer Baum. Die Knoten werden indiziert. So hat die Wurzel im Deap den Index 1, das kleinste Element im Baum den Index 2 und das größte den Index 3. Betrachtet man nun den Baum nur anhand seiner Indizes kann man diese Datenstruktur auch nur mit Hilfe eines Arrays realisieren. Um dann der logischen Baumstruktur weiterhin zu entsprechen sind folgende Formeln von Nöten: Das linke Kind eines Knoten: Das rechte Kind eines Knoten: IndexLinkesKind = 2 * IndexAktuellerKnoten IndexRechtesKind = 2 * IndexAktuellerKnoten + 1 Vater eines Knotens: IndexVater = IndexAktuellerKnoten / 2 (*) (*) Wenn nötig wird auf die nächst kleinere ganze Zahl abgerundet. Korrespondierender Partnerknoten: Dazu muss als erstes der Abstand zwischen beiden Knoten ermittelt werden. Abstand = 2 exp(p - 1) mit p = log2(IndexAktuellerKnoten) Um den Min-Partner zu ermitteln: IndexMinPartner = IndexAktuellerKnoten – Abstand Um den Max-Partner zu ermitteln: IndexMaxPartner = IndexAktuellerKnoten + Abstand Diese Formeln gelten für den Fall, dass die Indizierung mit eins begonnen wurde. Der Aufwand dieser Datenstruktur liegt bei O(n) = n * log2 (n). Verglichen mit dem Heap ist der Aufwand also gleich. Seite 4 von 4