Rev. 2, 19.06.2017 TU Ilmenau, Fakultät für Informatik und Automatisierung FG Komplexitätstheorie und Effiziente Algorithmen Univ.-Prof. Dr. M. Dietzfelbinger, M. Sc. Philipp Schlag, M. Sc. Stefan Walzer http://www.tu-ilmenau.de/iti/lehre/lehre-ss-2017/aud/ Algorithmen und Datenstrukturen SS 2017 – Hausaufgabe Organisation: Die Hausaufgabe wird in 3er- oder 4er-Gruppen bearbeitet1 ; die Lösungen werden kurz (mündlich) diskutiert. Jede Gruppe meldet sich ab Mittwoch, dem 21. Juni 2017, bei Jana Kopp (Zusebau, Raum 1046) an und wählt einen Diskussionstermin aus. Die fertige Implementierung dheap.h ist vor dem Diskussionstermin an [email protected] und [email protected] zu schicken. Senden Sie uns zudem Notizen zu Aufgaben 1 und 3 zu; Stichworte genügen, diese Aufgaben sind ohnehin auch Gegenstand der Diskussion. Aufgabe 1 (Heapsort mit D-ären Heaps) In dieser Hausaufgabe betrachten wir eine Heapsort-Variante, die D-äre Heaps statt binäre Heaps benutzt. D-äre Heaps sind eine Verallgemeinerung von binären Heaps: Jeder Knoten hat höchstens D (statt höchstens 2) Kinder. Analog zum (Standard-)Heapsort bildet man einen linksvollständigen D-ären Baum mit n Schlüsseln auf ein Array A[0..n−1] in Levelorder-Reihenfolge ab: A[0] A[1] A[D] A[2] ... A[D+1] A[2D] ... Die Heapbedingung gilt sinngemäß: Der Schlüssel jedes Knotens ist kleiner oder gleich dem Schlüssel all seiner Kinder. (a) Wiederholen Sie sorgfältig Heapsort aus Kapitel 6 der Vorlesung. Achtung: In der Vorlesung beginnen die Arrayindices bei 1, hier beginnen die Arrayindices bei 0! (b) Wir sagen Knoten v hat Index i“, falls A[i] den Eintrag von v speichert. Das k-te Kind vom Knoten v ” mit Index i hat Index ck (i), falls es existiert; der Vater von v hat Index p(i), falls er existiert. Finden Sie eine Formel für ck (i) für 0 ≤ i < n und 0 ≤ k < D und für p(i) für i > 0! (c) Wie unterscheiden sich BubbleDown, MakeHeap und HeapSelect bei Standard-Heapsort und bei Heapsort mit D-ären Heaps? 2 Algorithmen und Datenstrukturen SS 2017 – Hausaufgabe Aufgabe 2 (Implementierung von Heapsort mit D-ären Heaps) Ausgehend vom (Standard-)Heapsort wollen wir nun eine Implementierung mit D-ären Heaps umsetzen und testen. Vervollständigen Sie, mit Hilfe Ihrer Kenntnisse aus Aufgabe 1, die mit /// TODO ” Anfang“ und /// TODO Ende“ markierten Quelltextlücken in der Datei dheap.h! Schreiben Sie kei” ne zusätzlichen Klassen, Funktionen, etc. Kompilieren Sie das Programm und führen Sie es mit dem Parameter 1 aus (wenn Sie das bereitgestellte Code::Blocks Projekt benutzen, ist das die Konfiguration testHeap), um Ihre Implementierung zu testen. Hinweis: Falls Ihre Implementierung fehlerfrei ist, wird das Programm mit der Meldung Test abge” schlossen.“ beendet. Falls Ihre Implementierung fehlerhaft ist, bricht das Programm unter Umständen mit einer Fehlermeldung ab. Übersteht Ihre Implementierung den Test, ist es eher unwahrscheinlich, dass Ihre Implementierung fehlerhaft ist; Fehlerfreiheit kann jedoch nicht garantiert werden! Aufgabe 3 (Experimente mit D-ärem Heapsort) Wir möchten nun den Einfluss des Parameters D auf das Verhalten von D-ärem Heapsort in verschiedenen Situationen untersuchen. Von Interesse ist dabei die Frage, wie man D wählen sollte, falls Objektkopien langsam sind (Arrayelemente sind groß) bzw. Schlüsselvergleiche langsam sind (z. B. wenn die Schlüssel lange Strings sind). Des Weiteren möchten wir den Beitrag der Heapaufbauphase (MakeHeap) und der Heapentnahmephase (HeapSelect) zur Laufzeit untersuchen. Als zu sortierendes Array dient dabei in jedem Experiment eine uniform zufällig gewählte Permutation von {0, 1, . . . , n − 1} (Arrayelemente sind Schlüssel, kein Datenteil). Gemessene Laufzeiten und Vergleichsanzahlen sind stets Mittelwerte aus mindestens 10 Messungen. Wir führen folgende Experimente durch: • Experiment 1: Arrayelemente sind klein und Schlüsselvergleiche sind schnell. Für n = 1000000 werden Laufzeit und Vergleichsanzahl für D = 2, 3, . . . , 16 gemessen. • Experiment 2: Arrayelemente sind groß und Schlüsselvergleiche sind schnell. Für n = 1000000 werden Laufzeit und Vergleichsanzahl für D = 2, 3, . . . , 16 gemessen. • Experiment 3: Arrayelemente sind klein und Schlüsselvergleiche sind langsam. Für n = 1000000 werden Laufzeit und Vergleichsanzahl für D = 2, 3, . . . , 16 gemessen. • Experiment 4: Arrayelemente sind klein und Schlüsselvergleiche sind schnell. Für die Arraygrößen n = 5000, 10000, . . . , 100000 wird die Laufzeit je für MakeHeap und HeapSelect bei festem D gemessen. Hinweis: Stellen Sie beim Kompilieren stets sicher, dass Sie die Kompileroptimierung aktiviert haben! Experimente 1 − 3 werden durch Übergabe von Parameter 2 gestartet, Experiment 4 durch Parameter 3. (Wenn Sie das bereitgestellte Code::Blocks Projekt benutzen, wählen Sie einfach die Konfigurationen experiments1-3 bzw. experiments4.) Gehen Sie wie folgt vor: (a) Führen Sie Experimente 1 bis 3 durch, die Messwerte werden in Textdateien gespeichert. Führen Sie das entstandene Octave-Skript octave-experiments-1-3-online.m.txt zum Beispiel auf der Seite http://rextester.com/l/octave_online_compiler aus.) Beantworten Sie folgende Fragen: Algorithmen und Datenstrukturen SS 2017 – Hausaufgabe 3 (i) Welchen Einfluss hat der Parameter D auf die Laufzeit in den verschiedenen Situationen? Nennen Sie mögliche Ursachen! (ii) Welchen Zusammenhang zwischen der Laufzeit und der Anzahl an Schlüsselvergleichen können Sie beobachten? (b) Ermitteln Sie den Wert von D, für den in Experiment 1 die Laufzeit minimiert wird, und tragen Sie den Wert in die mit /// TODO Anfang Exp4“ und /// TODO Ende Exp4“ markierte Stelle ” ” in dheap.h als BEST D ein! Kompilieren Sie das Programm und führen Sie Experiment 4 durch (im Code::Blocks Projekt: Konfiguration experiment4). Führen Sie das entstandene Octave-Skript octave-experiments-4-online.m.txt wie gehabt aus. Beantworten Sie folgende Fragen: (i) Wie stark tragen MakeHeap und HeapSelect zur Gesamtlaufzeit bei? (ii) Welches Verhalten beobachten Sie bei steigender Arraygröße n? Nennen Sie mögliche Ursachen!